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);   //对TEA5767这三个延时都是必须的  
       GPIO_SetBits(GPIOA,PIN_SCL); 
       delay_us(5); 
       GPIO_ResetBits(GPIOA,PIN_SCL);
       delay_us(5);
    }  
}     

//读1个字节,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, &GPIO_InitStruct );
}

void delay_us(u32 m)
{
   while(m--)
   {
   }
}

 

你可能感兴趣的:(stm32)