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;
[*]}
一般用到I2C都是模拟的。。。
页:
[1]