历史上的今天
返回首页

历史上的今天

今天是:2025年05月20日(星期二)

正在发生

2018年05月20日 | STM32下模拟I2C的C语言实现

2018-05-20 来源:eefocus

近来主要在写一些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 u8  TWI_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 u8  TWI_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;  

}  


推荐阅读

史海拾趣

正泰公司的发展小趣事

2014年,正泰公司接到了一份来自美国光伏巨头SE的大订单。然而,客户对车间现场使用的安规测试仪的检测方法提出了质疑,要求限期完成整改。面对这一挑战,正泰公司的员工曹敬乐根据国际标准中的相关要求,结合实际参数,重新对检测工装进行改进设计和样品制备。经过不断测试和改进,最终满足了外方的要求,订单顺利投产。这一事件不仅展示了正泰公司的技术实力和创新能力,也体现了公司对市场变化的敏锐度和应对挑战的能力。

GC Electronics公司的发展小趣事
定期清洁传感器和冷却系统,防止污垢或杂质影响传感器的正常工作。
Datalogic公司的发展小趣事

Datalogic公司自成立以来,一直致力于技术创新。在1990年代,随着电子行业的快速发展,对高精度数据采集和处理的需求日益增加。Datalogic凭借其深厚的技术积累,成功研发出一系列高性能的条码扫描器和数据采集器,这些产品凭借其高效、稳定的表现,迅速在电子行业占据了一席之地。

Festo公司的发展小趣事

20世纪50年代,随着自动控制技术的发展和现代工业水平的不断提高,气动元件和气动系统得到了广泛的应用。被誉为“德国气动之父”的Kurt Stoll敏锐地发现了这一趋势,并领导Festo公司开始在这一领域进行深入的研发。通过不断的努力和创新,Festo成功开发出了一系列高性能的气动产品,并在市场上取得了巨大的成功。逐渐地,Festo成为了全球气动自动化领域的领导者。

Grand Halo Technology Co Ltd公司的发展小趣事

近年来,Festo在中国的发展步伐进一步加快。2021年4月,Festo济南全球生产中心正式全面投入运营。这个生产中心整合了本地的生产、研发、销售、物流等全价值链,形成了“研产销一体化”的格局。通过引进先进的生产设备和工艺,以及优化生产流程和管理体系,Festo济南全球生产中心在保障产品质量的同时,也大大提高了生产效率和响应速度。这一生产中心的建立不仅为Festo在中国市场的进一步发展提供了强有力的支持,也进一步巩固了Festo在全球气动自动化领域的领导地位。

以上五个故事从不同角度展示了Festo公司在电子行业中的发展历程和成就。作为一家以创新为驱动、以可持续发展为目标的公司,Festo将继续引领电子行业的发展方向,为全球客户提供更加优质的产品和服务。

Crane Connectors公司的发展小趣事

Crane Connectors公司自创立之初,便致力于电子连接器技术的研发与创新。面对激烈的市场竞争,公司不断投入研发资源,推出了一系列具有自主知识产权的新型连接器产品。这些产品凭借出色的性能、稳定性和可靠性,迅速获得了市场的认可,为公司赢得了大量订单。随着技术的不断升级和产品的持续优化,Crane Connectors逐渐在电子连接器领域树立了良好的品牌形象,实现了市场的快速扩张。

问答坊 | AI 解惑

dsp2835LED程序

看程序先看大的流程  然后再了解每个模块实现的细节…

查看全部问答>

[求助]2440 SDRAM升级

hi,大家好,因为开发需要,本人对原来的2440开发板进行了内存升级,从原来的64MB升级为128MB,使用的是两片K4S511632D(原来是两片HY57V561620),现在遇到的情况是写入一个字节的数据后一整片内存区域的数据都跟着改变,查了很久也找不到原因,SDR ...…

查看全部问答>

adoce3.1对数据库操作

if(FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))                 return FALSE;                 HRESULT hr;         CLSI ...…

查看全部问答>

請問smdk6400開機停在starting kernel...地問題

各位大大好 小弟想請教一下個問題 我在complier完load進smdk6400主板 但系統一開機執行到Starting kernel... 就當掉哩~~~ 有什麼方向可以去追緃嗎 謝謝~~~…

查看全部问答>

vc的测试程序 出现devintf.h错误 不知如何解决

#include \"D:\\Program Files\\NuMega\\DriverStudio\\DriverWorks\\include\\devintf.h\";出现了connot open include files:D:\\Program Files\\NuMega\\DriverStudio\\DriverWorks\\include\\devintf.h; no such file or directory 请教大虾 ...…

查看全部问答>

EVC4.0中,提示'TextOut' : is not a member of 'CClientDC'

代码如下:         char buff[10];         CClientDC dc(this);         sprintf(buff,\"[%o3d,%03d]\",point.x,point.y);             dc.Tex ...…

查看全部问答>

请问ARM编译器armv4l-unknown-linux和arm-linux的区别?

经常可以看到ARM的两种交叉编译器,armv4l-unknown-linux...和arm-linux...系列。有的板子好像都可以运行这两个编译器编译的程序。 不知道这两种交叉编译器有什么区别?…

查看全部问答>

好用的UART 程序

出自http://www.asic-world.com/。==========================================================================//-----------------------------------------------------// Design Name : uart // File Name   : uart.v// Function&nb ...…

查看全部问答>

谁用51单片机做过水平面水平度测试仪之类的东西呢?

最近开始要做一个水平测试仪之类的东西,但是没有思路  ,谁做过类似的东西可以给点参考什么的?小白一枚,求帮助,想通过做实际的东西提升自己下这方面的能力…

查看全部问答>

STM32F107VC金龙开发板 第十六章 红外解码

本帖最后由 旺宝电子 于 2015-4-22 17:25 编辑 第十六章 红外解码 16.1红外遥控简介:1、红外编解码在光谱中波长自0.76至400微米的一段称为红外线,红外线是不可见光线。为了防止自然界中的红外线干扰,一般对红外线进行编码调制后进行通信, ...…

查看全部问答>