《STM32从零开始学习历程》@EnzoReventon
相关链接:
I2C物理层介绍
I2C协议层介绍
I2C固件库介绍
STM32的I2C特性及架构介绍
STM32的EEPROM简介
参考资料:
[野火EmbedFire]《STM32库开发实战指南——基于野火霸天虎开发板》
[正点原子]STM32F4开发指南-库函数版本_V1.2
[ST]《STM32F4xx中文参考手册》
[ATMEL]《AT24C02说明书》
开发板硬件原理图;EEPROM原理图。
本实验所要完成的任务是通过I2C向EEPROM中发送一个字节的数据。
并且能够通过串口调试助手查看到发送状态与现实错误代码。
本实验采用的开发板为“正点原子”探索者F4开发板,核心芯片为F407ZGT6。
使用到的外设及硬件为:USART1,I2C1,EEPROM。
USART1:PA9(T)—》RXE;PA10(R) —》TXE,将引脚使用跳线帽相连接即可。
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO结构体
I2C_InitTypeDef I2C_InitStructure; //定义I2C结构体
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); //使能GPIOB时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); //使能I2C1时钟
GPIO_PinAFConfig(GPIOB,GPIO_PinSource8,GPIO_AF_I2C1); //复用PB8至I2C
GPIO_PinAFConfig(GPIOB,GPIO_PinSource9,GPIO_AF_I2C1); //复用PB9至I2C
//GPIOB8初始化SCL
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //开漏输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化
//GPIOB9初始化SDA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //开漏输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化
//初始化I2C结构体
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //使能ask响应
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit ; //设定7为地址
I2C_InitStructure.I2C_ClockSpeed = 400000; //设置时钟速度
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2 ; //指定时钟占空比1/2与9/16选择
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //设置为I2C模式
I2C_InitStructure.I2C_OwnAddress1 = 0x78; //指定自身的I2C设备地址。另一种说法:作为主机时可以不用写?
I2C_Init(I2C1,&I2C_InitStructure); //初始化结构体
I2C_Cmd(I2C1,ENABLE); //I2C使能
}
//========================================================================================
//定义一个超时常数
#define TIME_OUT 0x000FFFFF
uint32_t count_wait = TIME_OUT;
//========================================================================================
//addr:是要写入存储单元的地址
//date:是要写入的数据
uint8_t EEPROM_Byte_Write(uint8_t addr, uint8_t date)
{
//========================================================================================
//产生起始条件
I2C_GenerateSTART(I2C1,ENABLE); //产生开始信号
//重置count_wait
count_wait = TIME_OUT;
//等待EV5事件,直到成功
//checkevent函数为专门用来检查EVx标志位的函数
while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS )
{
count_wait--; //循环次数自减
if(count_wait == 0) //当循环次数减为0,标志程序运行着超时
{
return Error_Back(1);//表示程序执行卡死在EV5
}
}
//========================================================================================
//要发送的EEPROM设别地址 高四位:1010固定 低四位:A2 A1 A0 R/W 0 0 0 0 1010 0000 = 0xa0
I2C_Send7bitAddress(I2C1,0xa0,I2C_Direction_Transmitter);
//重置count_wait
count_wait = TIME_OUT;
//等待EV6事件,直到成功
while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS )
{
count_wait--;
if(count_wait == 0)
{
return Error_Back(2);
}
}
//========================================================================================
//发送要写入的存储单元的地址
I2C_SendData(I2C1,addr);
//重置count_wait
count_wait = TIME_OUT;
//等待EV8_2事件,直到成功
while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS )
{
count_wait--;
if(count_wait == 0)
{
return Error_Back(3);
}
}
//========================================================================================
//发送要写入的数据
I2C_SendData(I2C1,date);
//重置count_wait
count_wait = TIME_OUT;
//等待EV8_2事件,直到成功
while(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS )
{
count_wait--;
if(count_wait == 0)
{
return Error_Back(4);
}
}
//========================================================================================
//产生结束信号
I2C_GenerateSTOP(I2C1,ENABLE);
//表示程序执行正常
return 0;
}
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置系统中断优先级分组2
delay_init(168); //初始化延时函数
uart_init(115200); //初始化串口波特率为115200
LED_Init(); //初始化LED
LCD_Init(); //LCD初始化
KEY_Init(); //按键初始化
IIC_Init(); //I2C初始化
EEPROM_Byte_Write(0x05, 0x22); //向EEPROM的0x05的地址中写入0x22
printf("okok"); //若上一行代码没有卡死将输出okok
}
这个实验不难,主要是熟练以下寄存器的使用已经一个设计的流程,其次,代码功能的优化也是非常重要的,在文中,错误代码的显示以及程序超时这两个功能(从野火那儿学习来的)都是属于代码优化。所以我们要放宽视野,多学学人家良好的编程习惯。谢谢!请各位大佬不吝赐教!
xml ImageView android : id id/know_star android : layout_width fill_parent ...
想了解更多内容,请访问: 51CTO和华为官方战略合作共建的鸿蒙技术社区 https://...
IT之家3月12日消息 谷歌最近推出了 Chrome 浏览器 89 版本,对浏览器的配置文件...
使用原生Js实现随机点名 最近学了一点前端内容,老师让用js设计一个班里的随机点...
回忆一下查询成本 对于一个查询来说,有时候可以通过不同的索引或者全表扫描来执...
首先声明这篇文章不是标题党,我说的这个类库是 FreeSql.Repository,它作为扩展...
在实际Web开发中,插入图片、包含CSS文件等都需要有路径,如果文件路径的添加错...
抱歉,其实内容并不如题!!! 背景(写测试demo所出现的异常,供大家学习与拍砖...
本文实例总结了PHP常用字符串函数用法。分享给大家供大家参考,具体如下: 字符...
可能有人知道Cookie的生成由machineKey有关,machineKey用于决定Cookie生成的算...