打印
[新手园地]

M0助学板学习第二帖:IIC实验

[复制链接]
3000|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
mcsgy|  楼主 | 2011-9-19 23:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 mcsgy 于 2011-9-19 23:31 编辑

//////////////////////////////////////////////////////
//工程名称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。
}


IIC实验.rar (676.69 KB)


相关帖子

沙发
hotpower| | 2011-9-20 06:19 | 只看该作者
iic俺感觉还是用状态机更好理解。而且程序不会乱。

使用特权

评论回复
板凳
mcsgy|  楼主 | 2011-9-20 09:25 | 只看该作者
2# hotpower

恩,第一次用,能读写我就知足了。继续努力

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:从零开始

6

主题

232

帖子

1

粉丝