硬件实现IIC协议读取EEPROM
我TMD也是服了,反正我板子搞了半天也不成功我也不知道为什么,野火STM32-MINI,一直卡EV5,不管了 先代码沾上
工程目录(板子为野火STM32 MINI)
串口相关代码:
bsp_usart.h
#ifndef __USART_H
#define __USART_H #include "stm32f10x.h"
#include <stdio.h> /**
* 串口宏定义,不同的串口挂载的总线和IO不一样,移植时需要修改这几个宏
* 1-修改总线时钟的宏,uart1挂载到apb2总线,其他uart挂载到apb1总线
* 2-修改GPIO的宏
*/ // 串口1-USART1
#define DEBUG_USARTx USART1
#define DEBUG_USART_CLK RCC_APB2Periph_USART1
#define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART_BAUDRATE 115200 // USART GPIO 引脚宏定义
#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)
#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd #define DEBUG_USART_TX_GPIO_PORT GPIOA
#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9
#define DEBUG_USART_RX_GPIO_PORT GPIOA
#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10 #define DEBUG_USART_IRQ USART1_IRQn
#define DEBUG_USART_IRQHandler USART1_IRQHandler void USART_Config(void); #endif /* __USART_H */
bsp_usart.c
#include "./usart/bsp_usart.h" /**
* @brief USART GPIO 配置,工作参数配置
* @param 无
* @retval 无
*/
void USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure; // 打开串口GPIO的时钟
DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE); // 打开串口外设的时钟
DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE); // 将USART Tx的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure); // 将USART Rx的GPIO配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure); // 配置串口的工作参数
// 配置波特率
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
// 配置 针数据字长
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
// 配置停止位
USART_InitStructure.USART_StopBits = USART_StopBits_1;
// 配置校验位
USART_InitStructure.USART_Parity = USART_Parity_No ;
// 配置硬件流控制
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
// 配置工作模式,收发一起
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// 完成串口的初始化配置
USART_Init(DEBUG_USARTx, &USART_InitStructure); // 使能串口
USART_Cmd(DEBUG_USARTx, ENABLE);
} ///重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
/* 发送一个字节数据到串口 */
USART_SendData(DEBUG_USARTx, (uint8_t) ch); /* 等待发送完毕 */
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET); return (ch);
} ///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
/* 等待串口输入数据 */
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET); return (int)USART_ReceiveData(DEBUG_USARTx);
}
bsp_i2c_ee.h
#ifndef __I2C_EE_H
#define __I2C_EE_H #include "stm32f10x.h"
#include "bsp_usart.h" #define EEPROM_ADDR 0xA0 void I2C_EE_Config(void);
void EEPROM_Byte_Write(uint8_t addr,uint8_t data);
void EEPROM_Page_Write(uint8_t addr,uint8_t *data,uint8_t numByteToWrite);
void EEPROM_Read(uint8_t addr,uint8_t *data,uint8_t numByteToRead);
void EEPROM_WaitForWriteEnd(void); #endif /* __I2C_EE_H */
bsp_i2c_ee.c
#include "bsp_i2c_ee.h" void I2C_EE_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure; // 打开IIC GPIO的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 打开IIC 外设的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); // 将IIC SCL SDA的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置IIC的工作参数
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;//使能应答
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit ;//使用7位地址模式
I2C_InitStructure.I2C_ClockSpeed = 400000; //配置SCL时钟频率
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2 ;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C ;
I2C_InitStructure.I2C_OwnAddress1 = 0x5f; //这是STM32 IIC自身设备地址,只要是总线上唯一即可 I2C_Init(I2C1,&I2C_InitStructure); // 使能串口
I2C_Cmd (I2C1, ENABLE);
} //向EEPROM写入一个字节 void EEPROM_Byte_Write(uint8_t addr,uint8_t data)
{
//产生起始信号
I2C_GenerateSTART(I2C1,ENABLE); while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) == ERROR); //EV5事件被检测到,发送设备地址
I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter); while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) == ERROR); //EV6事件被检测到,发送要操作的存储单元地址
I2C_SendData (I2C1,addr); while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING ) == ERROR); //EV8事件被检测到,发送要存储的数据
I2C_SendData (I2C1,data); while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED ) == ERROR); //数据传输完成
I2C_GenerateSTOP(I2C1,ENABLE); } //向EEPROM写入多个字节(页写入),每次写入不能超过8个字节 void EEPROM_Page_Write(uint8_t addr,uint8_t *data,uint8_t numByteToWrite)
{
//产生起始信号
I2C_GenerateSTART(I2C1,ENABLE); while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) == ERROR); //EV5事件被检测到,发送设备地址
I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter); while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) == ERROR); //EV6事件被检测到,发送要操作的存储单元地址
I2C_SendData (I2C1,addr); while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING ) == ERROR); while(numByteToWrite)
{
//EV8事件被检测到,发送要存储的数据
I2C_SendData (I2C1,*data); while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED ) == ERROR); data++;
numByteToWrite--; }
//数据传输完成
I2C_GenerateSTOP(I2C1,ENABLE); } //从EEPROM读取数据 void EEPROM_Read(uint8_t addr,uint8_t *data,uint8_t numByteToRead)
{
//产生起始信号
I2C_GenerateSTART(I2C1,ENABLE); while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) == ERROR); //EV5事件被检测到,发送设备地址
I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter); while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ) == ERROR); //EV6事件被检测到,发送要操作的存储单元地址
I2C_SendData (I2C1,addr); while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTING ) == ERROR); //第二次起始信号
//产生起始信号
I2C_GenerateSTART(I2C1,ENABLE); while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) == ERROR); //EV5事件被检测到,发送设备地址
I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Receiver); while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) == ERROR); while(numByteToRead)
{
if(numByteToRead == 1)
{
//如果为最后一个字节
I2C_AcknowledgeConfig (I2C1,DISABLE);
} //EV7事件被检测到
while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED ) == ERROR); //EV7事件被检测到,即数据寄存器有新的有效数据
*data = I2C_ReceiveData(I2C1); data++; numByteToRead--; } //数据传输完成
I2C_GenerateSTOP(I2C1,ENABLE); //重新配置ACK使能,以便下次通讯
I2C_AcknowledgeConfig (I2C1,ENABLE); } //等待EEPROM内部时序完成
void EEPROM_WaitForWriteEnd(void)
{ do
{
//产生起始信号
I2C_GenerateSTART(I2C1,ENABLE); while(I2C_GetFlagStatus (I2C1,I2C_FLAG_SB) == RESET); //EV5事件被检测到,发送设备地址
I2C_Send7bitAddress(I2C1,EEPROM_ADDR,I2C_Direction_Transmitter);
}
while(I2C_GetFlagStatus (I2C1,I2C_FLAG_ADDR) == RESET ); //EEPROM内部时序完成传输完成
I2C_GenerateSTOP(I2C1,ENABLE);
}
main.c
#include "stm32f10x.h"
#include "./usart/bsp_usart.h"
#include "./i2c/bsp_i2c_ee.h" uint8_t readData[10]={0};
uint8_t writeData[8]={4,5,6,7,8,9,10,11};
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
uint8_t i=0;
USART_Config();
printf("这是一个IIC通讯实验\n"); I2C_EE_Config();
//向 EEPROM 11地址写入0x55,
EEPROM_Byte_Write(11,0x55);
EEPROM_WaitForWriteEnd();
//读出 EEPROM 11地址的内容,保存到readData中(数组的第一个址位)
EEPROM_Read(11,readData,1);
printf("%x",readData[0]); //addr%8 == 0 ,即为地址对齐
EEPROM_Page_Write(16,writeData,8); //等待写入操作完成
EEPROM_WaitForWriteEnd(); //读取数据
EEPROM_Read(16,readData,8);
for(i=0;i<8;i++)
{
printf("%d ",readData[i]);
}
while(1);
}
/*********************************************END OF FILE**********************/
硬件实现IIC协议读取EEPROM的更多相关文章
- 第十六章 IIC协议详解+UART串口读写EEPROM
十六.IIC协议详解+Uart串口读写EEPROM 本文由杭电网友曾凯峰根据小梅哥FPGA IIC协议基本概念公开课内容整理并最终编写Verilog代码实现使用串口读写EEPROM的功能. 以下为原文 ...
- IIC协议建模——读写EEPROM
案例采用明德扬设计思想完成.IIC协议是非常常用的接口协议,在电子类岗位招聘要求中经常出现它的身影.关于IIC协议这里只做简要介绍,详细信息请自行百度或查阅相关Datasheet,网上资料非常多.该篇 ...
- 基于STM8的IIC协议--实例篇--时钟模块(DS3231)读取
1. 综述 由上篇博客可知道IIC协议如何用代码实现,本篇博客就不涉及协议内容,只讲解如何使用. 本次的实验传感为:DS3231(时钟模块),对于时钟模块的具体信息我也就不多介绍,大家可以自行度娘,具 ...
- IIC协议理解(转)
目录 IIC协议理解(转) 个人小结记录 (记一下这个就够了) 以下为转载记录 概述 概述 输出级 主设备与从设备 速率 时序 空闲状态 起始位与停止位 数据的有效性 数据的传送 工作过程 主设备向从 ...
- IIC协议解释(转)
IIC协议解释 推荐资源: http://m.elecfans.com/article/574049.html and https://blog.csdn.net/firefl ...
- 【STM32】IIC的基本原理(实例:普通IO口模拟IIC时序读取24C02)(转载)
版权声明:本文为博主原创文章,允许转载,但希望标注转载来源. https://blog.csdn.net/qq_38410730/article/details/80312357 IIC的基本介绍 ...
- IIC协议解释
IIC协议解释 (1)概述 I2C(Inter-Integrated Circuit BUS) 集成电路总线,该总线由NXP(原PHILIPS)公司设计,多用于主控制器和从器件间的主从通信,在小数据量 ...
- IIC协议解析
(1)概述 I2C(Inter-Integrated Circuit BUS) 集成电路总线,该总线由NXP(原PHILIPS)公司设计,多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距 ...
- IIC协议学习笔记
"移植"的重要性:并非所有的电路都得自己设计,到了一定阶段,"移植"也是一种学习能力.--CrazyBingo 转眼间期末又到了,最近开始了所谓的期末总预习,比 ...
随机推荐
- select选中
比如<select class="selector"></select> 1.设置value为“全部“的项选中 复制代码代码如下: $(&quo ...
- 【解决方案】IP代理池设计与解决方案
一.背景 爬虫服务请求量大,为了应对反爬措施,增加爬虫的爬取效率和代理IP使用率,需要设计一个IP代理池,满足以下需求: 定时任务获取第三方代理 及时剔除IP代理池中失效的IP 业务隔离IP 若IP未 ...
- python3 各种编码转换
在做CTF密码题时很大的坑点就在编码,中间有一个弄错就出不来结果.正好python在这块比较坑,记录一下.以下是各种需求对应的输出: 1. 字符串转16进制ascii码串: txt='ABC' new ...
- GO --- 将Reader 或者 ReadCloser 转化为 ReadSeeker
原因: ReadSeeker 封装了Seek()方法,这个方法要求资源的任何位置都能被定位,例如存储在磁盘里文件,你可以随时读取文件的任意位置.而response.Body 是通过TCP连接从网络中读 ...
- linux内核中IS_ALIGNED是如何定义的?
1. 定义如下: (include/linux/kernel.h) #define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a ...
- python定义接口继承类
zxq547 python定义接口继承类invalid syntax解决办法 1 2 3 4 5 6 7 class s_all(metaclass=abc.ABCMeta): #python ...
- OSError: image file is truncated (28 bytes not processed)
解决办法: 在代码中添加两行 from PIL import ImageFile ImageFile.LOAD_TRUNCATED_IMAGES = True
- zblog模板怎么安装?zblog主题安装教程
有很多初次使用zblog的新手还会问我“zblog模板怎么安装?”,那么本文就专门给大家介绍下zblog主题安装教程. zblog现在分为zblogasp和zblogphp两个版本,两个版本的模板主题 ...
- Qt编写自定义控件53-自定义宽高下拉框
一.前言 默认的qcombobox控件,如果元素item中的内容过长超过控件本身的宽度的话,会自动切掉变成省略号显示,有些应用场景不希望是省略号显示,希望有多长就显示多长,还有一种应用场景是需要设置下 ...
- java 利用poi 实现excel合并单元格后出现边框有的消失的解决方法
使用工具类RegionUtil CellRangeAddress cra = new CellRangeAddress(nowRowCount, nowRowCount + followSize-1, ...