嵌入式蓝桥杯IIC通信程序编写
首先我们打开官方提供的驱动文件里包含了 IIC代码
路径如下
嵌入式设计与开发\I2C参考程序
把这两个工程加入我们的工程模板中
然后我们打开官方给我们AT24301的数据手册
找到地址位介绍的
可以看到地址位是由内存大小 A2 A1 P1 P0 R/W来决定的
于是我们打开官方给我们的原理图 找到IIC想对应的芯片
官方的是M24C02MN6和我们的有些出路
但是不重要 我们可以猜测出 E0 E1 E2对应的就是 A0 A1 A2
因为这三个引脚都是置地的 所以我们推出这三个位都是 低电平
所以这样我们就确定的我们要的地址位
如果我们要写(W)的话
我们的地址位是
1 0 1 0 0 0 0 (0)
【为什么写是0 请看下面读写时序图】
换算成十六进制就是 0xA0
如果我们要读(R)的话
1 0 1 0 0 0 0 (1)
【为什么写是1 请看下面读写时序图】
换算成十六进制就是 0xA1
接下来我们根据实实训图来编写我们的一个IIC读写程序
可以清楚的看到 R/W上面对应的 横线是在下面
所以推断楚W(写)是低电平
然后我们不用关注时序图的高低电平
因为官方给我们的库中已经写好相对应的函数
我们需要注意的是我们使用官方函数的顺序(只需看时序图的上方) 和ACK
注释:这个->DEVIE ADDRESS 其实对应下面8个字节就是我们前面提到的存储芯片的地址位 可以明显看到 前面是 1010 然后3个不确定位
和一个R\W都写位
[ACK 代表等待程序响应]
从左往右看
-> START
->DEVICE ADDRESS
->ACK
->WORD ADDRESS
->ACK
->DATA
->ACK
->STOP
从实训图中我们可以看出 我们不仅要发送
给元器件的地址
发要发送我们存储数据地址
以及我们要存储的数据
对此我们编写的我们的一个发送程序
void x24c02_write(unsigned char address,unsigned char info)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CSendByte(info);
I2CWaitAck();
I2CStop();
}
然后我们紧接着又来编写我们的读程序
然后从这个这个时序图可以看出
->START
->DEVIE ADDRESS
->ACK
->WROD ADRESS
->ACK
->START
->DEVEICE ADDRESS
->READ
->DATA
->NO ACK
->STOP
这个读取函数我们是用I2CReceiveByte()的返回值来读取的
程序源码如下
uint8_t x24c02_read(uint8_t address)
{
unsigned char val;
//发送芯片的写地址
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
val = I2CReceiveByte();
I2CWaitAck();
I2CStop();
return(val);
}
接着我们在主函数来实现这这个IIC的程序的功能
我们每次上电的 显示的上电数加1
int main(void)
{
uint8_t temp;
uint8_t string[20];
SysTick_Config(SystemCoreClock/1000); //1msÖжÏÒ»´Î
//LCD¹¤×÷ģʽÅäÖÃ
STM3210B_LCD_Init();
LCD_Clear(White);
LCD_SetTextColor(White);
LCD_SetBackColor(Blue);
LCD_ClearLine(Line0);
LCD_ClearLine(Line1);
LCD_ClearLine(Line2);
LCD_ClearLine(Line3);
LCD_ClearLine(Line4);
LCD_DisplayStringLine(Line1," I2C DEMO ");
LCD_DisplayStringLine(Line3," AT24C02 R/W ");
LCD_SetTextColor(Blue);
LCD_SetBackColor(White);
i2c_init();
temp = IIC_read(0xff);
Delay_Ms(2);
IIC_write(0xff,++temp);
Delay_Ms(2);
sprintf(string,"%s%d","ADDR:0xFF,VAL:",temp);
LCD_DisplayStringLine(Line6,string);
while(1){
}
}
下面是I2C.c的代码
/*
³ÌÐò˵Ã÷: CT117EǶÈëʽ¾ºÈü°åGPIOÄ£ÄâI2C×ÜÏßÇý¶¯³ÌÐò
Èí¼þ»·¾³: Keil uVision 4.10
Ó²¼þ»·¾³: CT117EǶÈëʽ¾ºÈü°å
ÈÕ ÆÚ: 2011-8-9
*/
#include "stm32f10x.h"
/** I2C ×ÜÏß½Ó¿Ú */
#define I2C_PORT GPIOB
#define SDA_Pin GPIO_Pin_7
#define SCL_Pin GPIO_Pin_6
#define FAILURE 0
#define SUCCESS 1
//ÅäÖÃSDAÐźÅÏßΪÊäÈëģʽ
void SDA_Input_Mode()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = SDA_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}
//ÅäÖÃSDAÐźÅÏßΪÊä³öģʽ
void SDA_Output_Mode()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = SDA_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}
//
void SDA_Output( uint16_t val )
{
if ( val ) {
GPIO_SetBits(I2C_PORT,SDA_Pin);
} else {
GPIO_ResetBits(I2C_PORT,SDA_Pin);
}
}
//
void SCL_Output( uint16_t val )
{
if ( val ) {
GPIO_SetBits(I2C_PORT,SCL_Pin);
} else {
GPIO_ResetBits(I2C_PORT,SCL_Pin);
}
}
//
uint8_t SDA_Input()
{
return GPIO_ReadInputDataBit( I2C_PORT, SDA_Pin);
}
//ÑÓʱ³ÌÐò
void delay1(unsigned int n)
{
unsigned int i;
for ( i=0;i<n;++i);
}
//I2C×ÜÏßÆô¶¯
void I2CStart(void)
{
SDA_Output(1);delay1(500);
SCL_Output(1);delay1(500);
SDA_Output(0);delay1(500);
SCL_Output(0);delay1(500);
}
//I2C×ÜÏßÍ£Ö¹
void I2CStop(void)
{
SCL_Output(0); delay1(500);
SDA_Output(0); delay1(500);
SCL_Output(1); delay1(500);
SDA_Output(1); delay1(500);
}
//µÈ´ýÓ¦´ð
unsigned char I2CWaitAck(void)
{
unsigned short cErrTime = 5;
SDA_Input_Mode();
delay1(500);
SCL_Output(1);delay1(500);
while(SDA_Input())
{
cErrTime--;
delay1(500);
if (0 == cErrTime)
{
SDA_Output_Mode();
I2CStop();
return FAILURE;
}
}
SDA_Output_Mode();
SCL_Output(0);delay1(500);
return SUCCESS;
}
//·¢ËÍÓ¦´ðλ
void I2CSendAck(void)
{
SDA_Output(0);delay1(500);
delay1(500);
SCL_Output(1); delay1(500);
SCL_Output(0); delay1(500);
}
//
void I2CSendNotAck(void)
{
SDA_Output(1);
delay1(500);
SCL_Output(1); delay1(500);
SCL_Output(0); delay1(500);
}
//ͨ¹ýI2C×ÜÏß·¢ËÍÒ»¸ö×Ö½ÚÊý¾Ý
void I2CSendByte(unsigned char cSendByte)
{
unsigned char i = 8;
while (i--)
{
SCL_Output(0);delay1(500);
SDA_Output(cSendByte & 0x80); delay1(500);
cSendByte += cSendByte;
delay1(500);
SCL_Output(1);delay1(500);
}
SCL_Output(0);delay1(500);
}
//´ÓI2C×ÜÏß½ÓÊÕÒ»¸ö×Ö½ÚÊý¾Ý
unsigned char I2CReceiveByte(void)
{
unsigned char i = 8;
unsigned char cR_Byte = 0;
SDA_Input_Mode();
while (i--)
{
cR_Byte += cR_Byte;
SCL_Output(0);delay1(500);
delay1(500);
SCL_Output(1);delay1(500);
cR_Byte |= SDA_Input();
}
SCL_Output(0);delay1(500);
SDA_Output_Mode();
return cR_Byte;
}
//I2C×ÜÏß³õʼ»¯
void i2c_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = SDA_Pin | SCL_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // **
GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}
//自己写的代码
void IIC_write(unsigned char address,unsigned char info)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CSendAck();
I2CWaitAck();
I2CStop();
}
u8 IIC_read(u8 adress)
{
unsigned char val;
I2CStart();
I2CSendByte(0XA0);
I2CWaitAck();
I2CSendByte(adress);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
val=I2CReceiveByte();
I2CWaitAck();
I2CStop();
return val;
}
i2c.h的代码
#ifndef __I2C_H__
#define __I2C_H__
#include "stm32f10x.h"
void i2c_init(void);
void delay1(unsigned int n);
void I2CStart(void);
void I2CStop(void);
void I2CSendAck(void);
void I2CSendNotAck(void);
unsigned char I2CWaitAck(void);
void I2CSendByte(unsigned char cSendByte);
unsigned char I2CReceiveByte(void);
void IIC_write(unsigned char address,unsigned char info);
u8 IIC_read(u8 adress);
#endif