I<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />2C存储器读写程序设计(三)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
一、命令处理程序的编写
1、如果输入命令i2cwr,以下程序将被执行。
void UartCmdI2CWrite(void){
static u8 I2CBuf[256]; u8 BufIndex="0"; u8 TempChar;
for ( ; ; ) //循环检测从串口消息队列里取出字符,遇到enter和esc退出
{ TempChar = Uart_GetChar();
if( TempChar=='\n') // 如果按下了Enter键,字符输入结束
{ // 下面将缓冲区数据写入24c02。
I2CBuf[BufIndex]='\0'; //BufIndex=输入字符的数字,命令缓冲区以0结束
Uart_PutString( "\r\n" ); //串口终端回显换行
if ( BufIndex==0 ) //之前没有输入字符,就是平白按了一下Enter
{ break; }
else //如果输入了字符,写入24C02
{ E2P_WriteMByte ( 0, I2CBuf, BufIndex+1 );
break;
}
}
else if ( TempChar==0x1B) //按下ESC时串口终端送过来为0x1B.
{
Uart_PutString( "\r\n" ); //串口中断回显换行
break; //退回到命令界面
}
else if ( TempChar=='\b') //如果输入退格键
{
if ( BufIndex==0 ) //之前没有输入字符,按退格不能理他
{ Speaker_Beep(); //警告,已经退回提示符了,再退就:>了。
}
else
{
BufIndex -=1; //有效字符数减去1.
Uart_PutChar( TempChar ); //让串口中断自己处理退格键
}
}
else //如果是其他键
{
I2CBuf[BufIndex]=TempChar; //将字符存入缓冲区当前位置
BufIndex +=1; //缓冲区位置向前移动
if (BufIndex>=I2CCap+1 ) //如果超过了,这个字符现在占据最后一个位置
{ BufIndex="I2CCap"; //使当前位置保持为最后一个,等待Enter。
Speaker_Beep(); //这个字符也不向字符界面输出,而是产生警告
}
else
{
Uart_PutChar( TempChar );//将有效字符输出。
}
}
}
}
2、如果输入命令i2crd,将执行程序void UartCmdI2CRead(void),详细的程序就不在这里列出了。
经过编译,这两个命令的执行成功,不过E2P_WriteMByte()此时只是一个框架,并没有真正的写入存储器,下面开始存储器读写框架程序的设计。
二、存储器读写框架程序的设计 (文件e2prom.c)
根据24c02的时序写了以下程序,其中有关I2C总线操作的部分基本是空函数,处理I2C_ReceivData(),每次返回一个8用于演示。程序编译,下载,成功运行。
void E2P_WriteMByte ( u8 AddIndex, u8* CharBuf, u16 CharCount){
u16 i;
I2C_Start(); //开启I2C总线传输。
I2C_SendAdd ( 0xA0 ); //发送控制字,传输方向写
I2C_SendData ( AddIndex ); //数据在存储器写初始位置
for ( i="0"; i<CharCount; i++ )
{
I2C_SendData ( CharBuf ); //传输数据
}
I2C_Stop();
}
void E2P_ReadMByte ( u8 AddIndex, u8* CharBuf, u16 CharCount ){
u16 i;
I2C_Start();
I2C_SendAdd ( 0xA0 );
I2C_SendData ( AddIndex );
I2C_SendAdd ( 0xA1 ); //发送控制字,传输方向读
for ( i="0"; i<CharCount-1; i++ )
{
CharBuf = I2C_ReceiveData ( );
I2C_Ack (0); //接收一个字节后,发送确认信号
}
CharBuf[CharCount-1] = I2C_ReceiveData ( );
I2C_Ack (0); //接收最后一个字节后,发送不确认信号
I2C_Stop(); //然后停止总线
}
void I2C_Start( void ){}
void I2C_SendAdd ( u8 AData ){ AData =AData;}
void I2C_SendData ( u8 SData ){ SData =SData;}
u8 I2C_ReceiveData ( void ){ return '8';} 用于程序结构验证
void I2C_Ack ( u8 Ack){ Ack = Ack;}
void I2C_Stop(){}
三、I2C总线驱动程序的设计 (文件i2c.c)
先要在stm32f10x_conf.h中对I2C进行定义。
void I2C_Start( void ){
I2C_GenerateSTART ( I2C1, ENABLE );
}
void I2C_SendAdd ( u8 AData ){
if ( AData == 0xA0 ) //24c02控制字,写,对于stm32控制器是写地址
{ I2C_Send7bitAddress ( I2C1, 0xA0, I2C_Direction_Transmitter ); }
else if ( AData == 0xA1 ) //24c02控制字,读
{ I2C_Send7bitAddress ( I2C1, 0xA0, I2C_Direction_Receiver ); }
}
void I2C_SendDat ( u8 SData ){
I2C_SendData ( I2C1, SData );}
u8 I2C_ReceiveDat ( void ){
return I2C_ReceiveData ( I2C1 );}
void I2C_Ack ( u8 Ack){
if ( Ack == 0 ) //收到数据后,是正常响应0,开启控制器的自动响应
{ I2C_AcknowledgeConfig ( I2C1, ENABLE ); }
else //收到数据后,不响应,利用关闭自动响应来实现。
{ I2C_AcknowledgeConfig ( I2C1, DISABLE ); }
}
void I2C_Stop(){
I2C_GenerateSTOP( I2C1, ENABLE );
}
以上函数主要利用STM32的库函数来实现。
四、I2C总线配置程序的设计
先使能时钟。
void I2C_Config(void){ //进行I2C总线的初始化配置
GPIO_InitTypeDef GPIO_InitStructure; //进行GPIO端口设置的数据结构
I2C_InitTypeDef I2C_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 ; /* 两个脚开漏输出 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //工作于i2c模式
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //
//7位地址位
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 200000 ; //200k
I2C_Init(I2C1, &I2C_InitStructure); /* 根据上面结构的参数对i2c1进行初始化 */
I2C_Cmd(I2C1, ENABLE); /* 使能I2C1 */
}
程序编译、下载,测试没有成功,初始化设置有些问题,明天继续努力。
用户190064 2009-11-6 16:37