ligang 发表于 2014-3-4 11:40:33

STM32下模拟I2C的C语言实现

本帖最后由 ligang 于 2014-3-4 11:42 编辑

近来主要在写一些STM32上的开发程序,由于STM32的固件库中,I2C模块实在是不好用,所以在采用了软件模拟的方法来实现。
具体的代码如下(在Keil下调试通过):

[*]#include "stm32f10x_lib.h"   
[*]
[*]//条件编译 1:使用软件模拟I2C   
[*]//#define PIN_SCL   GPIO_Pin_6   
[*]//#define PIN_SDA   GPIO_Pin_7   
[*]
[*]
[*]static __inline void TWI_SCL_0(void)      { GPIOB->BRR=PIN_SCL; }
[*]static __inline void TWI_SCL_1(void)      { GPIOB->BSRR=PIN_SCL;}
[*]static __inline void TWI_SDA_0(void)      { GPIOB->BRR=PIN_SDA; }
[*]static __inline void TWI_SDA_1(void)      { GPIOB->BSRR=PIN_SDA;}
[*]static __inline u8   TWI_SDA_STATE(void)      { return (GPIOB->IDR & PIN_SDA) != 0; }
[*]//static __inline void TWI_NOP(void)      {TWI_Delay(); }   
[*]
[*]static const u8 TWI_ACK   =0;
[*]static const u8 TWI_READY   =0;
[*]static const u8 TWI_NACK    =1;
[*]static const u8 TWI_BUS_BUSY    =2;
[*]static const u8 TWI_BUS_ERROR   =3;
[*]
[*]static const u8TWI_RETRY_COUNT = 3; //重试次数   
[*]
[*]extern void Delay_mS(u32 n);
[*]
[*]static void TWI_Initialize(void);
[*]static u8 TWI_START(void);
[*]static u8 TWI_START_SHT(void);
[*]static void TWI_STOP(void);
[*]static u8TWI_SendByte(u8 Data);
[*]static u8 TWI_ReceiveByte(void);
[*]static void TWI_SendACK(void);
[*]static void TWI_SendNACK(void);
[*]
[*]
[*]/*******************************************************************************
[*] * 函数名称:TWI_Delay                                                                     
[*] * 描    述:延时函数                                                                     
[*] *                                                                              
[*] * 输    入:无                                                                     
[*] * 输    出:无                                                                     
[*] * 返    回:无                                                                     
[*] * 作    者:                                                                     
[*] * 修改日期:2010年6月8日                                                                     
[*] *******************************************************************************/
[*]static void TWI_NOP(void)
[*]{
[*] vu32 i, j;
[*] vu32 sum = 0;
[*] i = 20;
[*] while(i--)
[*] {
[*]   for (j = 0; j < 10; j++)
[*]   sum += i;   
[*] }
[*] sum = i;
[*]}
[*]
[*]/*******************************************************************************
[*] * 函数名称:TWI_Initialize                                                                     
[*] * 描    述:I2C初始化函数                                                                     
[*] *                                                                              
[*] * 输    入:无                                                                     
[*] * 输    出:无                                                                     
[*] * 返    回:无                                                                     
[*] * 作    者:                                                                     
[*] * 修改日期:2010年6月8日                                                                     
[*] *******************************************************************************/
[*]static void TWI_Initialize(void)
[*]{
[*]GPIO_InitTypeDef GPIO_InitStructure;
[*]GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
[*]GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
[*]
[*]GPIO_InitStructure.GPIO_Pin = PIN_SDA;
[*]GPIO_Init(GPIOB, &GPIO_InitStructure);
[*]
[*]GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
[*]GPIO_InitStructure.GPIO_Pin = PIN_SCL;
[*]GPIO_Init(GPIOB, &GPIO_InitStructure);
[*]   
[*]TWI_SDA_1();
[*]TWI_SCL_0();   
[*]   
[*]//////DebugPrint("Software TWI Initializing...\n");   
[*]}
[*]
[*]/*******************************************************************************
[*] * 函数名称:TWI_START                                                                     
[*] * 描    述:发送启动                                                                     
[*] *                                                                              
[*] * 输    入:无                                                                     
[*] * 输    出:无                                                                     
[*] * 返    回:无                                                                     
[*] * 作    者:                                                                     
[*] * 修改日期:2010年6月8日                                                                     
[*] *******************************************************************************/
[*]static u8 TWI_START(void)
[*]{   
[*] TWI_SDA_1();   
[*] TWI_NOP();
[*]   
[*] TWI_SCL_1();   
[*] TWI_NOP();      
[*]
[*] if(!TWI_SDA_STATE())
[*] {
[*]////DebugPrint("TWI_START:BUSY\n");   
[*]return TWI_BUS_BUSY;
[*] }
[*] TWI_SDA_0();
[*] TWI_NOP();
[*]   
[*] TWI_SCL_0();   
[*] TWI_NOP();   
[*]
[*] if(TWI_SDA_STATE())
[*] {
[*]////DebugPrint("TWI_START:BUS ERROR\n");   
[*]return TWI_BUS_ERROR;
[*] }   
[*]   
[*] return TWI_READY;
[*]}
[*]
[*]/* --------------------------------------------------------------------------*/
[*]/**
[*] * @Brief:TWI_START_SHT
[*] *
[*] * @Returns:   
[*] */
[*]/* --------------------------------------------------------------------------*/
[*]static u8 TWI_START_SHT(void)
[*]{
[*]    TWI_SDA_1();
[*]    TWI_SCL_0();
[*]    TWI_NOP();
[*]
[*]    TWI_SDA_1();   
[*]    TWI_SCL_1();   
[*]    TWI_NOP();
[*]
[*]    if(!TWI_SDA_STATE())
[*]    {
[*]      return TWI_BUS_BUSY;
[*]    }
[*]    TWI_SDA_0();
[*]    TWI_NOP();
[*]
[*]    TWI_SCL_0();   
[*]    TWI_NOP();   
[*]
[*]    TWI_SCL_1();
[*]    TWI_NOP();
[*]
[*]    TWI_SDA_1();
[*]    TWI_NOP();
[*]
[*]    TWI_SCL_0();
[*]    TWI_NOP();
[*]
[*]    return TWI_READY;
[*]}
[*]
[*]/* --------------------------------------------------------------------------*/
[*]/**
[*] * @Brief:TWI_STOP
[*] */
[*]/* --------------------------------------------------------------------------*/
[*]static void TWI_STOP(void)
[*]{
[*] TWI_SDA_0();   
[*] TWI_NOP();
[*]   
[*] TWI_SCL_1();   
[*] TWI_NOP();      
[*]
[*] TWI_SDA_1();
[*] TWI_NOP();
[*]   
[*] //////DebugPrint("TWI_STOP\n");      
[*]}
[*]
[*]/* --------------------------------------------------------------------------*/
[*]/**
[*] * @Brief:TWI_SendACK
[*] */
[*]/* --------------------------------------------------------------------------*/
[*]static void TWI_SendACK(void)
[*]{
[*] TWI_SDA_0();
[*] TWI_NOP();
[*] TWI_SCL_1();
[*] TWI_NOP();
[*] TWI_SCL_0();   
[*] TWI_NOP();   
[*] TWI_SDA_1();
[*] //////DebugPrint("TWI_SendACK\n");      
[*]}
[*]
[*]/* --------------------------------------------------------------------------*/
[*]/**
[*] * @Brief:TWI_SendNACK
[*] */
[*]/* --------------------------------------------------------------------------*/
[*]static void TWI_SendNACK(void)
[*]{
[*] TWI_SDA_1();
[*] TWI_NOP();
[*] TWI_SCL_1();
[*] TWI_NOP();
[*] TWI_SCL_0();   
[*] TWI_NOP();
[*] //////DebugPrint("TWI_SendNACK\n");      
[*]}
[*]
[*]/* --------------------------------------------------------------------------*/
[*]/**
[*] * @Brief:TWI_SendByte
[*] *
[*] * @Param: Data
[*] *
[*] * @Returns:   
[*] */
[*]/* --------------------------------------------------------------------------*/
[*]static u8 TWI_SendByte(u8 Data)
[*]{
[*] u8 i;
[*] TWI_SCL_0();
[*] for(i=0;i<8;i++)
[*] {   
[*]//---------数据建立----------   
[*]if(Data&0x80)
[*]{
[*]   TWI_SDA_1();
[*]}
[*]else
[*]{
[*]   TWI_SDA_0();
[*]}   
[*]Data<<=1;
[*]TWI_NOP();
[*]//---数据建立保持一定延时----   
[*]   
[*]//----产生一个上升沿[正脉冲]   
[*]TWI_SCL_1();
[*]TWI_NOP();
[*]TWI_SCL_0();
[*]TWI_NOP();//延时,防止SCL还没变成低时改变SDA,从而产生START/STOP信号   
[*]//---------------------------      
[*] }
[*] //接收从机的应答   
[*] TWI_SDA_1();   
[*] TWI_NOP();
[*] TWI_SCL_1();
[*] TWI_NOP();   
[*] if(TWI_SDA_STATE())
[*] {
[*]TWI_SCL_0();
[*]TWI_SDA_1();
[*]//////DebugPrint("TWI_NACK!\n");   
[*]return TWI_NACK;
[*] }
[*] else
[*] {
[*]TWI_SCL_0();
[*]TWI_SDA_1();
[*]//////DebugPrint("TWI_ACK!\n");   
[*]return TWI_ACK;   
[*] }      
[*]}
[*]
[*]/* --------------------------------------------------------------------------*/
[*]/**
[*] * @Brief:TWI_ReceiveByte
[*] *
[*] * @Returns:   
[*] */
[*]/* --------------------------------------------------------------------------*/
[*]static u8 TWI_ReceiveByte(void)
[*]{
[*] u8 i,Dat;
[*] TWI_SDA_1();
[*] TWI_SCL_0();   
[*] Dat=0;
[*] for(i=0;i<8;i++)
[*] {
[*]TWI_SCL_1();//产生时钟上升沿[正脉冲],让从机准备好数据   
[*]TWI_NOP();   
[*]Dat<<=1;
[*]if(TWI_SDA_STATE()) //读引脚状态   
[*]{
[*]   Dat|=0x01;   
[*]}   
[*]TWI_SCL_0();//准备好再次接收数据   
[*]TWI_NOP();//等待数据准备好            
[*] }
[*] //////DebugPrint("TWI_Dat:%x\n",Dat);   
[*] return Dat;
[*]}

清风明月 发表于 2015-5-15 10:44:18

一般用到I2C都是模拟的。。。
页: [1]
查看完整版本: STM32下模拟I2C的C语言实现