打印
[Cortex-M0技术交流]

菜鸟学习M0第十六帖——I2C

[复制链接]
3624|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lixiaoxu2meng|  楼主 | 2011-9-24 11:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
I2c, TI, IO, gp, TE
本工程实现I2C的读写AT24L16 工程部分参照了 官方的固件库 以及三心前辈的例子 在此声明并对三心前辈表示感谢
main函数
/*---------------------------------------------------------------------------------------------------------*/
/* */
/* Copyright(c) 2011 Nuvoton Technology Corp. All rights reserved. */
/* */
/*---------------------------------------------------------------------------------------------------------*/
#include "includes.h" //包含所需的头文件
/*************************************************************************************
** Function name: main
** Descriptions: 本函数实现:I2C功能,向AT24C16的0x00地址写入0x03 然后读出来 并用数码管显示出来
注:本例程的I2C读写部分移植了论坛三心前辈的例子 特此声明并感谢三心前辈
** input parameters: 无
** output parameters: 无
** Returned value: 无
*************************************************************************************/
int main (void)
{
Set_System(); //封装一些初始化模块
I2C_WriteByte (0x00,0x03 );
delay_ms(1000);
value = I2C_ReadByte(0x00);
while(1)
{}
}


hw_config函数
#include "includes.h" //包含所需的头文件
/*************************************************************************************
** Function name: Set_System
** Descriptions: 封装一些初始化模块
** input parameters: count
** output parameters: 无
** Returned value: 无
*************************************************************************************/
void Set_System(void)
{
RCC_Configuration(); //配置系统时钟

GPIO_Configuration(); //配置GPIO

TIMER_Configuration(); //配置TIMER

I2C_Configuration(); //配置I2C
}
/*************************************************************************************
** Function name: RCC_Configuration
** Descriptions: 系统时钟源设置
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void RCC_Configuration(void)
{
UNLOCKREG(); // 对写保护位操作时 需要一次向0x50000 0100写入 0x59,0x16,0x88,
DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1);// 与其 SYSCLK->PWRCON.XTL12M_EN = 1; 等同
// PWRCON寄存器(这些寄存器在上电复位到用户解锁定之前是锁定的)除了 BIT[6]位其他位都受写保护
// 解除这些需要向 0x50000 0100写入 0x59,0x16,0x88,
// 令PWRCON寄存器的BITP[0]为1(即设定12M外部晶振)
delay_ms(100); // while (DrvSYS_GetChipClockSourceStatus(E_SYS_XTL12M) != 1);//等待外部12MHZ晶振就绪
LOCKREG(); // 向“0x5000_0100”写入任何值,就可以重锁保护寄存器
}
/*************************************************************************************
** Function name: GPIO_Configuration
** Descriptions: GPIO配置
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void GPIO_Configuration()
{
DrvGPIO_Open( E_GPA, 2, E_IO_OUTPUT );//数码管段选
DrvGPIO_Open( E_GPA, 3, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 4, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 5, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 6, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 7, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 8, E_IO_OUTPUT );
DrvGPIO_Open( E_GPA, 9, E_IO_OUTPUT );
DrvGPIO_Open( E_GPC, 14, E_IO_OUTPUT );//数码管位选
DrvGPIO_Open( E_GPC, 15, E_IO_OUTPUT );
DrvGPIO_Open( E_GPC, 6, E_IO_OUTPUT );
DrvGPIO_Open( E_GPC, 7, E_IO_OUTPUT );
}
/*************************************************************************************
** Function name: TIMER_Configuration
** Descriptions: TIMER配置
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void TIMER_Configuration()
{
DrvTIMER_Init(); //初始化定时器

DrvSYS_SelectIPClockSource(E_SYS_TMR0_CLKSRC,0); //使用外设时注意必须设置该外设的时钟 设置TIMER0的时钟源为外部12MHZ

DrvTIMER_Open(E_TMR0,1000,E_PERIODIC_MODE); //设定定时器timer0的tick周期,并且启动定时器:定时器通道 TMR0 每秒1000次 周期模式

DrvTIMER_SetTimerEvent(E_TMR0,5,(TIMER_CALLBACK) Timer0_Callback,0); //安装一个定时处理事件到 timer0通道

DrvTIMER_EnableInt(E_TMR0); //使能定时器中断 //TIMER0->TCSR.IE = 1

DrvTIMER_Start(E_TMR0); //定时器timer0开始计数 //TIMER0->TCSR.CEN = 1;
}
/*************************************************************************************
** Function name: Timer0_Callback
** Descriptions: 定时处理事件,LED动态扫描
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void Timer0_Callback (void)
{
static uint8_t count= 0;
static uint8_t i,xx[4];
uint32_t data;
uint16_t ValueBuff ;
ValueBuff = value;
count++;
if(count >= 5)
count = 1;
for(i=0;i<4;i++)
{
xx[i] = ValueBuff%10;
ValueBuff = ValueBuff/10;
}
switch(count)
{
case 1:
DrvGPIO_SetBit(E_GPC,14);
DrvGPIO_ClrBit(E_GPC,15);
DrvGPIO_ClrBit(E_GPC,6);
DrvGPIO_ClrBit(E_GPC,7);
data = Table[xx[0]]<<2;
GPIOA->DOUT = data;
break;
case 2:
DrvGPIO_SetBit(E_GPC,15);
DrvGPIO_ClrBit(E_GPC,14);
DrvGPIO_ClrBit(E_GPC,6);
DrvGPIO_ClrBit(E_GPC,7);
data = Table[xx[1]]<<2;
GPIOA->DOUT = data;
break;
case 3:
DrvGPIO_SetBit(E_GPC,7);
DrvGPIO_ClrBit(E_GPC,14);
DrvGPIO_ClrBit(E_GPC,15);
DrvGPIO_ClrBit(E_GPC,6);
data = Table[xx[2]]<<2;
GPIOA->DOUT = data;
break;
case 4:
DrvGPIO_SetBit(E_GPC,6);
DrvGPIO_ClrBit(E_GPC,14);
DrvGPIO_ClrBit(E_GPC,15);
DrvGPIO_ClrBit(E_GPC,7);
data = Table[xx[3]]<<2;
GPIOA->DOUT = data;
//DrvGPIO_ClrBit(E_GPA,9); //显示小数点
break;
default:break;
}
}
/*************************************************************************************
** Function name: I2C_Configuration
** Descriptions: I2C配置(注:一些配置都在 读写I2C的子程序里了)
** input parameters: none
** output parameters: none
** Returned value: none
*************************************************************************************/
void I2C_Configuration()
{
DrvGPIO_InitFunction(E_FUNC_I2C1);//注意:在使用引脚特殊功能时 必须进行复用功能引脚设置(此时I2C1引脚为开漏输出)
DrvGPIO_SetBit(E_GPA,10); //在使用之前需将 I2C1_SDA 置高
DrvGPIO_SetBit(E_GPA,11); //在使用之前需将 I2C1_SCL 置高
}
/*************************************************************************************
** Function name: I2C_WriteByte
** Descriptions: I2C向写单字节函数(注:此函数是将论坛三心前辈的例子移植过来的 在此声明并表示感谢)
** input parameters: 地址:address 数据:data
** output parameters: none
** Returned value: none
*************************************************************************************/
void I2C_WriteByte ( uint32_t address,uint8_t data )
{
/*
在字节写模式下,主器件发送起始命令和从器件地址信息(R/W 位置 0)给从器件,
主器件在收到从器件产生应答信号后,主器件发送1个8位字节地址写入AT24C01/
02/04/08/16 的地址指针,对于 AT24C31/64/128/256 来说,所不同的是主器件
发送两个8位地址字写入AT24C32/64/128/256的地址指针。主器件在收到从器件的
另一个应答信号后,再发送数据到被寻址的存储单元。AT24Cxx 再次应答,并在
主器件产生停止信号后开始内部数据的擦写,在内部擦写过程中,AT24Cxx 不再
应答主器件的任何请求。
*/
uint32_t i;

DrvI2C_Open(I2C_PORT1, 100000); //打开I2C1功能,并配置 I2C总线时钟为100KHZ (该函数进行了四舍五入操作)
/* Parameters:port - [in] I2C_PORT0 / I2C_PORT1 */
/* u32BusClock - [in] I2C bus clock frequency (Hz) */

DrvI2C_Ctrl(I2C_PORT1, 1, 0, 0, 0); //设定I2C控制位 START
/* Parameters:port - [in] I2C_PORT0 / I2C_PORT1 */
/* start - [in] 1:Enable / 0:Disable I2C开始 进入主机模式 */
/* stop - [in] 1:Enable / 0:Disable I2C停止 */
/* intFlag - [in] Wrtie '1' to clear this flag (I2C_SI) */
/* ack - [in] 1:Enable / 0:Disable 应答位 */
while (I2C1->CON.SI == 0); //查询中断标志位 SI 如果忙则一直等待

//I2C1->DATA = ;
DrvI2C_WriteData (I2C_PORT1, 0xA0);//发送写命令 即从器件地址
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //清标志位 SI
while( I2C1->CON.SI == 0 ); //查询中断标志位 SI

I2C1->DATA = address&0XFF; //发送地址
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //清标志位 SI 并使能应答
while( I2C1->CON.SI == 0 ); //查询中断标志位 SI 如果忙则一直等待

I2C1->DATA = data; //发送待写内容
DrvI2C_WriteData (I2C_PORT1, data);//发送写入的数据
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //清标志位 SI 并使能应答
while( I2C1->CON.SI == 0 ); //查询中断标志位 SI 如果忙则一直等待

DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0); //清标志位 SI 并STOP

for(i=0;i<60;i++);
DrvI2C_Close(I2C_PORT1); //关闭I2C1功能

for(i=0;i<6000;i++);
for(i=0;i<6000;i++);
}
/*************************************************************************************
** Function name: I2C_ReadByte
** Descriptions: I2C向读单字节函数(注:此函数是将论坛三心前辈的例子移植过来的 在此声明并表示感谢)
** input parameters: 地址:address
** output parameters: DATA
** Returned value: none
*************************************************************************************/
uint8_t I2C_ReadByte ( uint32_t address )
{
/*
随机读操作允许主器件对寄存器的任意字节进行读操作,主器件
首先通过发送起始信号、从器件地址和它想读取的字节数据的地
址执行一个伪写操作。在AT24Cxx 应答之后,主器件重新发送起
始信号和从器件地址,此时R/W 位置1,AT24CXX 响应并发送应答
信号,然后输出所要求的一个 8位字节数据,主器件不发送应答
信号但产生一个停止信号。
*/
uint8_t DATA;

DrvI2C_Open(I2C_PORT1, 100000); //打开I2C1功能,并配置 I2C总线时钟为100KHZ

DrvI2C_Ctrl(I2C_PORT1, 1, 0, 1, 0); //设定I2C控制比位 START并清中断标志
while (I2C1->CON.SI == 0); //查询中断标志位 SI 如果忙则一直等待

DrvI2C_WriteData (I2C_PORT1, 0xA0); //发送写命令 即从器件地址
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //清标志位 SI
while( I2C1->CON.SI == 0 ); //查询中断标志位 SI 如果忙则一直等待

DrvI2C_WriteData (I2C_PORT1, address&0xFF); //发送需要读写的地址
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //清标志位 SI 并使能应答
while( I2C1->CON.SI == 0 ); //查询中断标志位 SI 如果忙则一直等待

DrvI2C_Ctrl(I2C_PORT1, 1, 0, 1, 0); //设定I2C控制比位 START并清中断标志
while( I2C1->CON.SI == 0 ); //查询中断标志位 SI 如果忙则一直等待

DrvI2C_WriteData (I2C_PORT1, 0xA1); //发送写命令 即从器件地址的最低位 R/W 位设置为 1
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //清标志位 SI 并使能应答
while( I2C1->CON.SI == 0 ); //查询中断标志位 SI 如果忙则一直等待

//I2C1->DATA = 0xFF; //通过操作数据寄存器配合控制位的设置启动一次新的I2C操作(此句加与不加未影响到结果)
/*"Software should load the data byte (to be transmitted)into I2DAT before new I2CON setting is done." 手册中该句怎么解释?*/
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //清标志位 SI
while( I2C1->CON.SI == 0 ); //查询中断标志位 SI 如果忙则一直等待
DATA= DrvI2C_ReadData(I2C_PORT1); //读数据

DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0); //清标志位 SI 并STOP

DrvI2C_Close(I2C_PORT1); //关闭I2C1功能

return DATA;
}
/*************************************************************************************
** Function name: delay_ms
** Descriptions: 1ms(晶振为12MHZ)延时子程序
** input parameters: count
** output parameters: 无
** Returned value: 无
*************************************************************************************/
void delay_ms(uint32_t count)
{
uint32_t i,j;
for(i=count;i>0;i--)
for(j=2395;j>0;j--);
}

hw_config头文件
#ifndef __HW_CONFIG_H__
#define __HW_CONFIG_H__
void Set_System(void);
void RCC_Configuration(void);
void GPIO_Configuration(void);
void TIMER_Configuration(void);
void Timer0_Callback (void);
void I2C_Configuration(void);
void I2C_WriteByte ( uint32_t address,uint8_t data );
uint8_t I2C_ReadByte ( uint32_t address );
void delay_ms(uint32_t count);
#endif

已测试通过 OK
工程 LI-I2C.rar (1.2 MB)

相关帖子

沙发
296895536| | 2013-3-20 11:30 | 只看该作者
下载学习。  感谢LZ:victory:

使用特权

评论回复
板凳
a437916817| | 2013-4-9 15:18 | 只看该作者
多谢楼主多次分享,菜鸟学习了。。
劳烦继续分享啊。。

使用特权

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

本版积分规则

0

主题

1679

帖子

2

粉丝