[STM32F1] STM32基础篇 LCD—— IIC 实验

[复制链接]
3544|30
 楼主| aizaixiyuanqian 发表于 2018-2-12 19:28 | 显示全部楼层
高四位 1010 是 24Cxx 系列的固定器件地址,接下来是 A2、A1、A0 是根据器件连接来
决定,也就是我们原理图上面的 E2、E1、E0。我们的原理图都接地所以是 000。R/W 为
是选择读还是写,1 的时候是读,0 的时候是写。所以写的地址为 0xA0,读地址为 0xA1。
 楼主| aizaixiyuanqian 发表于 2018-2-12 19:29 | 显示全部楼层
STM32  的硬件 I2C  简介
STM32 的硬件 I2C 做得很复杂,而且不好用。所以大部分人都不太选择使用 STM32 的硬
件 I2C,很难调试。不过 AT24C02 有 ARM 官方的提供的例程,读写还是挺稳定的,我
们的例程使用的也是参考 ARM 官方的例程来的。接下来我们看看一下通过库函数使用硬
件 I2C 来操作 AT24C02。
 楼主| aizaixiyuanqian 发表于 2018-2-12 19:30 | 显示全部楼层
首先我们要打开时钟使能
要打开 GPIOB 的时钟使能。代码如下:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
 楼主| aizaixiyuanqian 发表于 2018-2-12 19:30 | 显示全部楼层
  配置 IO  的模式
GPIO_InitStructure.GPIO_Pin=I2C_SCL|I2C_SDA;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
管脚的端口定义如下:
//如果移植程序时只要改一下三个地方就行了
/* 定时使用的 IO 口 */
#define I2C_SCL GPIO_Pin_10 //PB10
#define I2C_SDA GPIO_Pin_11 //PB11
#define GPIO_I2C GPIOB
 楼主| aizaixiyuanqian 发表于 2018-2-12 19:30 | 显示全部楼层
AT24C02  写 操作
首先我们来看一下写 AT24C02。
一般步骤是:
1) 发送起始信号
2) 发送写器件地址
3) 等待应答
4) 发送要写入的 24C02 的地址
5) 等待应答
6) 发送要写入的数据
7) 等待应答
8) 发送数据结束发送结束信号
 楼主| aizaixiyuanqian 发表于 2018-2-12 19:31 | 显示全部楼层
具体程序如下:
void AT24Cxx_WriteOneByte(u16 addr,u8 dt)
{
I2C_Start();
if(EE_TYPE>AT24C16)
{
I2C_Send_Byte(0xA0);
I2C_Wait_Ack();
I2C_Send_Byte(addr>>8); //发送数据地址高位
}
else
{
I2C_Send_Byte(0xA0+((addr/256)<<1));//器件地址+数据地址
}
I2C_Wait_Ack();
I2C_Send_Byte(addr%256);//双字节是数据地址低位
//单字节是数据地址低位
I2C_Wait_Ack();
I2C_Send_Byte(dt);
I2C_Wait_Ack();
I2C_Stop();
delay_ms(10);
}
 楼主| aizaixiyuanqian 发表于 2018-2-12 19:37 | 显示全部楼层
读取 AT24C02 的步骤是:
1) 发送起始信号
2) 发送写器件地址
3) 等待应答
4) 发送要读取的 AT24C02 的地址
5) 等待应答
6) 再发送其实信号
7) 发送读器件地址
8) 等待应答
9) 接收数据
10) 如果没有接收完数据,发送应答
11) 接收数据
12) 直到接收完数据,发送非应答
13) 发送结束信号
 楼主| aizaixiyuanqian 发表于 2018-2-12 19:37 | 显示全部楼层
u8 AT24Cxx_ReadOneByte(u16 addr)
{
u8 temp=0;
I2C_Start();
if(EE_TYPE>AT24C16)
{
I2C_Send_Byte(0xA0);
I2C_Wait_Ack();
I2C_Send_Byte(addr>>8);  //发送数据地址高位
}
else
{
I2C_Send_Byte(0xA0+((addr/256)<<1));//器件地址+数据地址
}
I2C_Wait_Ack();
I2C_Send_Byte(addr%256);//双字节是数据地址低位
//单字节是数据地址低位
I2C_Wait_Ack();
I2C_Start();
I2C_Send_Byte(0xA1);
I2C_Wait_Ack();
temp=I2C_Read_Byte(0); // 0 代表 NACK
I2C_NAck();
I2C_Stop();
return temp;
}
 楼主| aizaixiyuanqian 发表于 2018-2-12 19:38 | 显示全部楼层
主函数
int main()
{
u8 wdata=0,value;
u8 i,j,dat[6],dat1[6];
I2C_INIT();
TFT_Init(); //TFT 彩屏初始化
LED_Init(); //端口初始化
key_init(); //按键初始化
printf_init(); //printf 初始化
TFT_ClearScreen(BLACK); //清屏
GUI_Show12ASCII(10,10,"This is a IIC-AT24C02 Check!",YELLOW,BLACK);
GUI_Show12ASCII(10,27,"PB10 PB11 is IIC Interface!",YELLOW,BLACK);
GUI_Show12ASCII(10,44,"The K_UP is:AT24C02 Write",YELLOW,BLACK);
GUI_Show12ASCII(10,61,"The K_DOWM is:AT24C02 Read",YELLOW,BLACK);
GUI_Show12ASCII(10,100,"Write data Range is: 0-255",YELLOW,BLACK);
GUI_Show12ASCII(10,150,"Write data is:",YELLOW,BLACK);
GUI_Show12ASCII(10,167,"Read data is:",YELLOW,BLACK);
while(1)
{
if(k_up==1) //按键 k_up 按下写入数据
{
delay_ms(10);
if(k_up==1)
{
AT24Cxx_WriteOneByte(0,++wdata);//写入的是单字节,0-255 取值范围
dat[0]=wdata/100+0x30;
dat[1]=wdata%100/10+0x30;
dat[2]=wdata%100%10+0x30;
dat[3]='\0';
GUI_Show12ASCII(160,150,dat,YELLOW,BLACK);
}
// while(k_up);
}
if(k_down==0)  //读取数据
{
delay_ms(10);
if(k_down==0)
{
value=AT24Cxx_ReadOneByte(0);
dat1[0]=value/100+0x30;
dat1[1]=value%100/10+0x30;
dat1[2]=value%100%10+0x30;
dat1[3]='\0';
GUI_Show12ASCII(160,167,dat1,YELLOW,BLACK);
}
while(!k_down);
}
if(j>1)
{
j=0;
GPIO_SetBits(GPIOC,GPIO_Pin_0);
}
else
{
j++;
GPIO_ResetBits(GPIOC,GPIO_Pin_0);
}
delay_ms(200);
}
}
 楼主| aizaixiyuanqian 发表于 2018-2-12 19:38 | 显示全部楼层
该函数实现按键  按下写入数据加 1 写入到 24C02 中,当按键 K_DOWN 按下后进行 24C02
的数据读取,LED 闪烁表示系统正在运行。
 楼主| aizaixiyuanqian 发表于 2018-2-12 19:39 | 显示全部楼层
这次的实验只是在iic的基础上增加了TFT
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部