资讯详情

stm32软件模拟I2C读取ADXL345三轴加速度值

最近实验室需要做一个小项目。stm32来读取ADXL345三轴加速值,原硬件I2C都调好了,但是后来和实验室合作的公司给的板子没有硬件I2C引出端口太难过了。我得重新调整软件I2C,因为我刚接触stm32.我以前从未接触过单片机等编程,所以我花了很多精力,对于网上给的程序,我找了几个都不好用,但是我暂时学会了I2C协议,参考各种在线版本的程序,比较I2C时序图,一点一点写出这个程序,幸好折腾了一天,程序居然好用,心里真的很开心。

I2C代码如下:

azhu_i2c.h:

 #ifndef  __AZHU_I2C_H #define  __AZHU_I2C_H   #include "stm32f10x.h"    #define PIN_SCL    GPIO_Pin_6 #define PIN_SDA    GPIO_Pin_5 #define I2C_PORT   GPIOA   //SDA的方向设置 void SDA_IN(void);  void SDA_OUT(void);   //I2C所有操作函数 void I2C_Init(void);                   //初始化I2C的IO口      void I2C_Start(void);                  //发送I2C开始信号 void I2C_Stop(void);                   //发送I2C停止信号 void I2C_Send_Byte(u8 txd);            //I2C发送字节 u8 I2C_Read_Byte(unsigned char ack);   //I2C读取一个字节 u8 I2C_Wait_Ack(void);                 //I2C等待ACK信号 void I2C_Ack(void);                    //I2C发送ACK信号 void I2C_NAck(void);                   //I2C不发送ACK信号 void I2C_Write_One_Byte(u8 daddr,u8 addr,u8 data); ///写字节 u8 I2C_Read_One_Byte(u8 daddr,u8 addr);            ///读一个字节 void delay_us(u32 m);                              ///延迟函数 #endif 

azhu_i2c.c:

#include "azhu_i2c.h"   void I2C_Init(void) {              GPIO_InitTypeDef GPIO_InitStructure;    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); //使A口时钟         GPIO_InitStructure.GPIO_Pin = PIN_SCL | PIN_SDA;    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;       //推挽输出    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    GPIO_Init(I2C_PORT, &GPIO_InitStructure); }   //产生I2C开始信号 void I2C_Start(void) {    SDA_OUT();                    //sda线输出    GPIO_SetBits(GPIOA,PIN_SDA);  //SDA =1    delay_us(10);    GPIO_SetBits(GPIOA,PIN_SCL);  //SCL=1    delay_us(10);    GPIO_ResetBits(GPIOA,PIN_SDA);//SDA=0    delay_us(10);    GPIO_ResetBits(GPIOA,PIN_SCL);//SCL=0 }     //产生I2C停止信号 void I2C_Stop(void) {    SDA_OUT();  //sda线输出    GPIO_ResetBits(GPIOA,PIN_SDA);       delay_us(10);    GPIO_SetBits(GPIOA,PIN_SCL);     delay_us(10);    GPIO_SetBits(GPIOA,PIN_SDA);     delay_us(10);    GPIO_ResetBits(GPIOA, PIN_SCL);//SCL=0;     delay_us(10);           } //等待响应信号到来 //返回值:1.接收应答失败 //        0,成功接收答案 u8 I2C_Wait_Ack(void) {    u8 ucErrTime=0;    SDA_IN();      //SDA设置为输入      GPIO_SetBits(GPIOA,PIN_SDA);    delay_us(5);        GPIO_SetBits(GPIOA,PIN_SCL);     delay_us(5);      while(GPIO_ReadInputDataBit(GPIOA,PIN_SDA))    {       ucErrTime  ;       if(ucErrTime>250)       {          I2C_Stop();          return 1;       }    }    GPIO_ResetBits(GPIOA, PIN_SCL);        return 0;   }   //产生ACK应答 void I2C_Ack(void) {    GPIO_ResetBits(GPIOA,PIN_SCL);    SDA_OUT();    GPIO_ResetBits(GPIOA,PIN_SDA);    delay_us(5);    GPIO_SetBits(GPIOA,PIN_SCL);    delay_us(5);    GPIO_ResetBits(GPIOA,PIN_SCL); }   //不产生ACK应答       void I2C_NAck(void) {    GPIO_ResetBits(GPIOA,PIN_SCL);    SDA_OUT();    GPIO_SetBits(GPIOA,PIN_SDA);    delay_us(5);    GPIO_SetBits(GPIOA,PIN_SCL);     delay_us(5);    GPIO_ResetBits(GPIOA,PIN_SCL); }                 //I2C发送字节 ////返回从机是否回应 //1,有回应 //0,无应答      void I2C_Send_Byte(u8 txd) {                             u8 t;        SDA_OUT();           GPIO_ResetBits(GPIOA,PIN_SCL);///数据传输始于拉下时钟     for(t=0;t<8;t  )     {                       if((txd&0x80)==0x80)              {GPIO_SetBits(GPIOA, PIN_SDA);}//SDA=1,写 1                         else             {GPIO_ResetBits(GPIOA, PIN_SDA);}//SDA=0,写 0          txd<<=1;            delay_us(5);   //对TEA五七六七这三个延迟都是必须的          GPIO_SetBits(GPIOA,PIN_SCL);         delay_us(5);         GPIO_ResetBits(GPIOA,PIN_SCL);        delay_us(5);     }   }        ///读一个字节,ack=1时,发送ACK,ack=0,发送nACK    u8 I2C_Read_Byte(unsigned char ack) {     unsigned char i,receive=0;     SDA_IN();//SDA设置为输入     for(i=0;i<8;i   )  {         GPIO_ResetBits(GPIOA,PIN_SCL);         delay_us(5);         GPIO_SetBits(GPIOA,PIN_SCL);         receive<<=1;         if(GPIO_ReadInputDataBit(GPIOA,PIN_SDA))receive  ;            delay_us(5);      }           if (!ack)         I2C_NAck();//发送nACK     else         I2C_Ack(); //发送ACK        return receive; } void SDA_IN(void) {    GPIO_InitTypeDef GPIO_InitStruct;    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;    //上拉输入    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;    GPIO_InitStruct.GPIO_Pin = PIN_SDA;    GPIO_Init(GPIOA, &GPIO_InitStruct ); } void SDA_OUT(void) {    GPIO_InitTypeDef GPIO_InitStruct;    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;    GPIO_InitStruct.GPIO_Pin = PIN_SDA;    GPIO_Init(GPIOA, &GPI_InitStruct );
}
 
void delay_us(u32 m)
{
   while(m--)
   {
   }
}

作者:azhuty 来源:CSDN 原文:https://blog.csdn.net/azhuty/article/details/22264999 版权声明:本文为博主原创文章,转载请附上博文链接!

标签: 加速度传感器adxl345stm32三轴加速度传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台