目录
前言
1. IIC基本原理
2. 电路原理
3. 代码编程
3.1 预备工作
3.2 AT24C02写读功能编写
3.2.1 AT24C02写操作实现
3.2.2 AT24C02读操作实现
3.3 MCP4017写读功能编写
3.3.1 MCP4017写操作实现
3.3.2 MCP4017读操作实现
3.4 main.c编写
3.4.1 头文件引用
3.4.2 变量声明
3.4.3 液晶屏显示代码
3.4.4 编写主要main函数部分
4. 测试
5. 总结
前言
因本人备赛蓝桥杯嵌入式省赛,故编写此学习笔记进行学习上的记录。
上文我们实现了UART程序设计,本文我们进行异步的串口通信的程序设计。
1. IIC基本原理
I2C(IIC,Inter-Intergrated Circuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备。
它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。
IIC是半双工通信方式。
IIC总线是不同IC或模块之间的双向两线通信,这两条是串行数据线(SDA)和串行时钟线(SCL)。这两条线必须通过上拉电路连接至电源。数据传输只能在总线不忙时启动。
2. 电路原理
蓝桥杯嵌入式主要考察利用IIC原理去读取24C02存储器和MCP4017可编程电阻的读写,并已给出参考历程。
下图所示为MCP4017可编程电阻的内部示意图,A点悬空,如上图所示W和B分别接了VDD和GND,所以MCP4017可编程电阻的实际电阻值就是W与B之间的阻值。
如下图所示,其中编程电阻其实就是改变N。
Rwb的实际计算方式如下图所示,其中翻阅手册得知Rab为100k
不考虑Rw的影响,每一个编程电阻分量值(N属于1~127)为0.7874k,由竞赛板的电路图可以计算出Vwb的电压为V。
3. 代码编程
3.1 预备工作
将竞赛公开包中的i2c_hal.c和i2c_hal.h文件分别拷贝到Test\Test_Project\Src\BSP\I2C\和Test\Test_Project\Inc\BSP\I2C\中,并更名为bsp_i2c.c和bsp_i2c.h(可以不改,为了规范😄)。打开Test_Project工程,进行文件Group的添加
更改bsp_i2c.c的依赖头文件
#include "I2C/bsp_i2c.h"
注意,这里需要修改bsp_i2c.c中的unsigned char I2CWaitAck(void)函数内容,将SDA_Output_Mode()挪到delay1(DELAY_TIME)后。修改后的结果如下:
unsigned char I2CWaitAck(void)
{
unsigned short cErrTime = 5;
SDA_Input_Mode();
delay1(DELAY_TIME);
SCL_Output(1);
delay1(DELAY_TIME);
while(SDA_Input())
{
cErrTime--;
delay1(DELAY_TIME);
if (0 == cErrTime)
{
SDA_Output_Mode();
I2CStop();
return ERROR;
}
}
SCL_Output(0);
delay1(DELAY_TIME);
SDA_Output_Mode();//本行代码改到delay1(DELAY_TIME)之后
return SUCCESS;
}
接下来进行24C02存储器和MCP4017可编程电阻的函数的编写。
3.2 AT24C02写读功能编写
3.2.1 AT24C02写操作实现
1KB/2KB EEPROM能进行8字节页面写入,4KB、8KB和16KB设备能进行16字节写入。激发写页面写操作时序图如下
写页面时序
AT24C02的芯片地址为1010(二进制),十进制为A,(W=0,R=1)
所以写的器件地址为0xA0
根据时序图编写AT24C02存储器的写操作
//AT24C02的写
void iic_24c02_write(unsigned char *pucBuf, unsigned char ucAddr, unsigned char ucNum)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(ucAddr);
I2CWaitAck();
while(ucNum--)
{
I2CSendByte(*pucBuf++);
I2CWaitAck();
}
I2CStop();
delay1(500);
}
3.2.2 AT24C02读操作实现
随机地址读取时序如图所示。随机读取需要一个空字节写序列来载入数据地址。
顺序读取时序如图所示。顺序读取由立即地址读取或随机地址读取激发。
根据时序图编写AT24C02存储器的读操作
//AT24C02的读
void iic_24c02_read(unsigned char *pucBuf, unsigned char ucAddr, unsigned char ucNum)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(ucAddr);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
while(ucNum--)
{
*pucBuf++ = I2CReceiveByte();
if(ucNum)
I2CSendAck();
else
I2CSendNotAck();
}
I2CStop();
}
3.3 MCP4017写读功能编写
3.3.1 MCP4017写操作实现
根据读时序,编写写电阻操作代码
//MCP4017写电阻
void write_registor(uint8_t value)
{
I2CStart();
I2CSendByte(0x5E);
I2CWaitAck();
I2CSendByte(value);
I2CWaitAck();
I2CStop();
}
3.3.2 MCP4017读操作实现
根据读时序,编写读电阻操作代码
//MCP4017写读电阻
uint8_t read_registor(void)
{
uint8_t value;
I2CStart();
I2CSendByte(0x5F);
I2CWaitAck();
value = I2CReceiveByte();
I2CSendNotAck();
I2CStop();
return value;
}
3.4 main.c编写
3.4.1 头文件引用
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "LCD\bsp_lcd.h"
#include "I2C\bsp_i2c.h"
3.4.2 变量声明
//变量声明
__IO uint32_t uwTick_Lcd_Set_Point;//LCD减速
//*LCD显示专用变量
unsigned char Lcd_Disp_String[22];
//EEPROM的相关变量
unsigned char EEPROM_String_1[5] = {0x11,0x22,0x33,0x44,0x55};
unsigned char EEPROM_String_2[5] = {0};
//R4017
uint8_t R4017;
3.4.3 液晶屏显示代码
void Lcd_Proc(void)
{
if((uwTick - uwTick_Lcd_Set_Point)<200)
return;
uwTick_Lcd_Set_Point = uwTick;
sprintf((char*)Lcd_Disp_String,"EE:%x,%x,%x,%x,%x",EEPROM_String_2[0],EEPROM_String_2[1],EEPROM_String_2[2],EEPROM_String_2[3],EEPROM_String_2[4]);
LCD_DisplayStringLine(Line2,Lcd_Disp_String);
sprintf((char*)Lcd_Disp_String,"R:%5.2fKQ",0.7874*R4017);
LCD_DisplayStringLine(Line3,Lcd_Disp_String);
sprintf((char*)Lcd_Disp_String,"Voltage:%6.3fV",3.3*0.7874*R4017/(0.7874*R4017+10));
LCD_DisplayStringLine(Line4,Lcd_Disp_String);
}
3.4.4 编写主要main函数部分
int main(void)
{
HAL_Init();
SystemClock_Config();
LCD_Init();
LCD_Clear(White);
LCD_SetBackColor(White);
LCD_SetTextColor(Blue);
I2CInit();
//读写M24C02存储器
iic_24c02_write(EEPROM_String_1,0,5);
HAL_Delay(1);
iic_24c02_read(EEPROM_String_2,0,5);
//读写MCP4017
write_registor(0x0D);
HAL_Delay(1);
R4017 = read_registor();
while (1)
{
Lcd_Proc();
}
}
4. 测试
如果测试成功,则屏幕上会显示写入EEPROM1的数据,R电阻和电压值
由图可以看到,代码测试成功。
5. 总结
本文进行IIC的介绍,并利用IIC原理去实现了读取24C02存储器和MCP4017可编程电阻的读写,通过代码测试成功实现了存储器和可编程电阻的读写功能。