[国嵌攻略][153][I2C裸机驱动设计]
eeprom简介
eeprom电可擦除可编程只读存储器,是一种类似于flash的固态存储器,但是与flash相比又存在一些区别:
1.eeprom可以按位擦写,而flash只能大片擦除。
2.eeprom一般容量都不大,一般都在64kb以下。
I2C初始化
在ARM内部有I2C控制器,可以对I2C器件进行访问。所以I2C初始化也就是对I2C控制器初始化。
1.如果需要,写入处理器的I2C从设备地址。
2.设置IICCON寄存器
2.1.允许中断
2.2.设置SCL周期
3.设置IICSTAT允许串行输出
4.设置GPIO为I2C
5.允许产生ACK
I2C写数据
1.设置处理器为主设备加发送模式
2.将从设备的地址写入到IICDS寄存器
3.写入0xF0到IICSATA
4.等到ACK的产生
5.写入字节地址到IICDS寄存器
6.等待ACK产生
7.将要传输的数据写入IICDS寄存器
8.清除中断
9.等待ACK的产生
10.写入0xD0到IICSATA
11.清除中断
I2C读数据
1.设置为主设备发送模式
2.写入从设备地址
3.写入0xF0到IICSTAT
4.等待ACK
5.写入eeprom内部地址
6.等待ACK
7.设置为主设备接收模式
8.写入从设备地址到IICDS
9.写入0xB0到IICSTAT开始接收
10.等待中断
11.1.如果是最后一个信号回答NO ACK
11.2.从IICDS里取出数据
12.清除中断
13.写入0x90到IICSTAT寄存器
14.清除中断
iic.c
/******************************************************************** *名称:iic.c *作者:D *时间:2016.03.16 *功能:AT24C08A EEPROM驱动 *********************************************************************/ /******************************************************************** *宏定义 *********************************************************************/ #define GPECON ( (*(volatile unsigned long *)0x56000040) ) //GPE组控制寄存器 #define GPEUP ( (*(volatile unsigned long *)0x56000048) ) //GPE组上拉寄存器 #define INTMSK ( (*(volatile unsigned long *)0x4A000008) ) //中断掩码寄存器 #define SRCPND ( (*(volatile unsigned long *)0X4A000000) ) //中断源请求寄存器 #define INTPND ( (*(volatile unsigned long *)0X4A000010) ) //中断请求寄存器 #define IICCON ( (*(volatile unsigned char *)0x54000000) ) //IIC总线控制寄存器 #define IICSTAT ( (*(volatile unsigned char *)0x54000004) ) //IIC总线状态寄存器 #define IICDS ( (*(volatile unsigned char *)0x5400000C) ) //IIC数据移位寄存器 /******************************************************************** *函数原型 *********************************************************************/ void init_iic(); void byte_write(unsigned char address, unsigned char data); void random_read(unsigned char address, unsigned char data[], int length); void iic_irq(); void delay_iic(int count); void test_iic(); /******************************************************************** *名称:init_iic *参数: * none *返回: * none *功能:初始化IIC控制器 *********************************************************************/ void init_iic(){ //配置功能引脚 GPECON &= ~((0x3<<30)|(0x3<<28)); GPECON |= ((0x2<<30)|(0x2<<28)); //GPE14[29:28]:IICSCL, GPE14[31:30]:IICSDA GPEUP |= (0x3<<14); //GPE[15:15]:The pull up function is disabled //设置中断标志 INTMSK &= ~(1<<27); //INT_IIC[27]:0 SRCPND |= (1<<27); //INT_IIC[27]:0 INTPND |= (1<<27); //INT_IIC[27]:0 //使能中断功能 IICCON |= (1<<5); //Tx/Rx Interrupt[5]:Enable //设置应答信号 IICCON |= (1<<7); //Acknowledge generation[7]:Enable //设置时钟周期 IICCON &= ~(1<<6); //Tx clock source selection[7]:IICCLK = fPCLK / 16 = 50MHz / 16 = 3125KHZ IICCON &= ~(0xF<<0); //Transmit clock value[3:0]:0 IICCON |= (0x5<<0); //Transmit clock value[3:0]:IICCLK/(IICCON[3:0]+1) = 3125KHz / 16 = 520KHz //打开串行输出 IICSTAT |= (1<<4); //Serial output[4]:Enable Rx/Tx } /******************************************************************** *名称:byte_write *参数: * address 数据地址 * data 数据内容 *返回: * none *功能:按字节写设备 *********************************************************************/ void byte_write(unsigned char address, unsigned char data){ //设置发送模式 IICSTAT |= (0x3<<6); //写入设备地址 IICDS = 0xA0; //向从设备写入数据 //打开发送模式 IICSTAT = 0xF0; //等待应答信号 while( (IICCON & (1<<4)) == 0 ){ delay_iic(10); } //写入数据地址 IICDS = address; //清除等待标志 IICCON &= ~(1<<4); //等待应答信号 while( (IICCON & (1<<4)) == 0 ){ delay_iic(10); } //写入数据内容 IICDS = data; //清除等待标志 IICCON &= ~(1<<4); //等待应答信号 while( (IICCON & (1<<4)) == 0 ){ delay_iic(10); } //关闭发送模式 IICSTAT = 0xD0; //清除等待标志 IICCON &= ~(1<<4); //等待结束生效 delay_iic(10); } /******************************************************************** *名称:random_read *参数: * address 数据地址 * data 数据内容 * length 数据长度 *返回: * none *功能:随机读设备 *********************************************************************/ void random_read(unsigned char address, unsigned char data[], int length){ //设置发送模式 IICSTAT |= (0x3<<6); //写入设备地址 IICDS = 0xA0; //向从设备写入数据 //打开发送模式 IICSTAT = 0xF0; //等待应答信号 while( (IICCON & (1<<4)) == 0 ){ delay_iic(10); } //写入数据地址 IICDS = address; //清除等待标志 IICCON &= ~(1<<4); //等待应答信号 while( (IICCON & (1<<4)) == 0 ){ delay_iic(10); } //关闭发送模式 IICSTAT = 0xD0; //清除等待标志 IICCON &= ~(1<<4); //等待结束生效 delay_iic(10); //设置接收模式 IICSTAT &= ~(0x3<<6); IICSTAT |= (0x2<<6); //写入设备地址 IICDS = 0xA1; //从从设备读取数据 //打开接收模式 IICSTAT = 0xB0; //等待应答信号 while( (IICCON & (1<<4)) == 0 ){ delay_iic(10); } //空读接收数据 unsigned char temp; temp = IICDS; //清除等待标志 IICCON &= ~(1<<4); //等待应答信号 while( (IICCON & (1<<4)) == 0 ){ delay_iic(10); } //读取接收数据 int i; for(i = 0; i < length; i++){ //读取数据内容 data[i] = IICDS; //清除等待标志 IICCON &= ~(1<<4); //判断接收长度 if(i < (length - 1)){ //等待应答信号 while( (IICCON & (1<<4)) == 0 ){ delay_iic(10); } }else{ //发送停止应答 IICCON &= ~(1<<7); } } //关闭接收模式 IICSTAT = 0x90; //清除等待标志 IICCON &= ~(1<<4); //等待结束生效 delay_iic(10); } /******************************************************************** *名称:iic_irq *参数: * none *返回: * none *功能:iic中断服务 *********************************************************************/ void iic_irq(){ //清除中断源请求 SRCPND |= (1<<27); //INT_IIC[27]:0 //清除中断请求 INTPND |= (1<<27); //INT_IIC[27]:0 } /******************************************************************** *名称:delay_iic *参数: * count 延时次数 *返回: * none *功能:延时函数 *********************************************************************/ void delay_iic(int count){ int i, j; for(i = 0; i < count; i++){ for(j = 0; j < 1000; j++){ } } } /******************************************************************** *名称:test_iic *参数: * none *返回: * none *功能:测试AT24C08A *********************************************************************/ void test_iic(){ //向EEPROM写入数据 int i; for(i = 0; i < 10; i++){ byte_write(i, i); } //从EEPROM读取数据 unsigned char buf[10]; random_read(0, buf, 10); //显示数据 for(i = 0; i < 10; i++){ printf("%d ", buf[i]); } printf("\n"); }