- //////////////////////////////////////////////////////
- //工程名称IIC实验
- //日期:2011年9月20日
- //作者:mcsgy
- //参考:系统函数驱动,Cube的GPIO实验项目
- //参考:STM32不完全手册IIC实验部分
- //参考:(电子write_cai)https://bbs.21ic.com/frame.php?frameon=yes&referer=http%3A//bbs.21ic.com/icnewest.html
- //////////////////////////////////////////////////////
- #include "NUC1xx.h"
- #include "iic.h"
- #define I2C_STA 0x20
- #define I2C_STO 0x10
- #define I2C_SI 0x08
- #define I2C_AA 0x04
- //I2C1的功能使能
- void I2C_GPIO_Init(void)
- {
- SYS->GPAMFP.I2C1_SDA_nWR=1;
- SYS->GPAMFP.I2C1_SCL_nRD=1;
- }
- //打开I2C
- int32_t I2C_Open(uint32_t u32BusClock)
- {
- uint32_t divider; //I2C clock = I2C source clock / (4*(divider+1))
- divider = (uint32_t) (((SystemCoreClock*10)/(u32BusClock * 4) + 5) / 10 - 1); ///* Compute proper divider for I2C clock */
- SYSCLK->APBCLK.I2C1_EN = 1; //使能I2C时钟
- SYS->IPRSTC2.I2C1_RST = 1; //复位I2C设备
- SYS->IPRSTC2.I2C1_RST = 0;
- I2C1->CON.ENSI = 1; //使能I2C控制
- I2C1->CLK = divider; //设置I2C波特率400kHz为最大
- return 0;
- }
- //关闭I2C
- int32_t I2C_Close(void)
- {
- I2C1->CON.ENSI = 0;
- SYS->IPRSTC2.I2C1_RST = 1;
- SYS->IPRSTC2.I2C1_RST = 0;
- SYSCLK->APBCLK.I2C1_EN = 0;
- return 0;
- }
- //获取I2C状态
- uint32_t I2C_GetStatus(void)
- {
- return I2C1->STATUS;
- }
- //写控制位函数
- void I2C_Ctrl(uint8_t start, uint8_t stop, uint8_t intFlag, uint8_t ack)
- {
- uint32_t Reg = 0;
-
- if (start)
- Reg |= I2C_STA;
- if (stop)
- Reg |= I2C_STO;
- if (intFlag)
- Reg |= I2C_SI;
- if (ack)
- Reg |= I2C_AA;
- *((__IO uint32_t *)&I2C1->CON) = (*((__IO uint32_t *)&I2C1->CON) & ~0x3C) | Reg;
- }
- //提数据
- uint8_t I2C_ReadData(void)
- {
- return I2C1->DATA;
- }
- //写数据
- void I2C_WriteData(uint8_t u8data)
- {
- I2C1->DATA = u8data;
- }
- //写入一个字节函数
- void WriteByte(uint16_t addr,uint8_t data) //addr 为数据要存储的地址,data为要写入的数据
- {
- I2C_Open(400000); //打开IIC1设备
- I2C_Ctrl(1,0,1,0); //启动Start
- while(0==(I2C1->CON.SI));
- I2C_WriteData(0xA0); //写从设备地址1010(A2)(A1)(A0)(W/R)
- I2C_Ctrl(0,0,1,0); //清SI标志位
- while(0==(I2C1->CON.SI));
- I2C_WriteData((uint8_t)(addr/256)); //写AT24C16存储器高地址
- I2C_Ctrl(0,0,1,1);
- while(0==(I2C1->CON.SI));
- I2C_WriteData((uint8_t)(addr%256)); //写AT24C16存储器低地址
- I2C_Ctrl(0,0,1,1);
- while(0==(I2C1->CON.SI));
- I2C_WriteData(data); //写入数据
- I2C_Ctrl(0,0,1,1);
- while(0==(I2C1->CON.SI)); //发STOP信号
- I2C_Ctrl(0,1,1,0);
- I2C_Close(); //关闭IIC1设备
- }
- uint8_t ReadByte(uint16_t addr) //addr 为要读出字节的地址
- {
- uint8_t temp;
- I2C_Open(400000); //打开IIC1设备
- I2C_Ctrl(1,0,1,0); //发Start信号
- while(0==(I2C1->CON.SI));
- I2C_WriteData(0xA0);
- I2C_Ctrl(0,0,1,0);
- while(0==(I2C1->CON.SI));
- I2C_WriteData((uint8_t)(addr/256));
- I2C_Ctrl(0,0,1,1);
- while(0==(I2C1->CON.SI));
- I2C_WriteData((uint8_t)(addr%256));
- I2C_Ctrl(0,0,1,1);
- while(0==(I2C1->CON.SI));
- I2C_Ctrl(1,0,1,0); //发Start信号
- while(0==(I2C1->CON.SI));
- I2C_WriteData(0xA1); //发“读”信号
- I2C_Ctrl(0,0,1,1);
- while(0==(I2C1->CON.SI));
- I2C_Ctrl(0,0,1,0);
- while(0==(I2C1->CON.SI));
- temp=I2C_ReadData();
- I2C_Ctrl(0,1,1,0);
- I2C_Close(); //关闭IIC1设备
- return temp;
- }
- //设置I2C时钟
- int32_t I2C_SetClockFreq(uint32_t u32BusClock)
- {
- uint32_t divider;
- divider = (uint32_t) (((SystemCoreClock*10)/(u32BusClock * 4) + 5) / 10 - 1);
- I2C1->CLK = divider;
- return 0;
- }
- //整个I2C初始化函数
- void I2C_Init(void)
- {
- I2C_GPIO_Init();
- I2C_Open(400000); //打开I2C硬件并配置时钟总线400KHZ;
- I2C_SetClockFreq (400000);//给I2C配置时钟频率;
- I2C_GetStatus (); //获取I2C状态码;
- I2C_WriteData(0); //写字节;
- I2C_ReadData(); //读字节;
- I2C_Ctrl(0, 0, 0, 0); //设定I2C控制位,包括控制寄存器中的STA, STO, AA, SI。
- }