STM8S_库函数_IIC接口_IO软件模拟_硬件实现

大家好,我是单片机爱好者-MCU起航。这一节我们介绍如何使用库函数方式控制STM8S103F3P6片上的IIC接口,也有的叫I2C。首先,我们看一下原理图,找到IIC接口的位置:

如图所示,在STM8S103F3P6的PB4和PB5管脚上,这是单片机自带的硬件IIC。学过51单片机的朋友,都接触过IIC。通过用普通的IO模拟IIC的时序,和24C02这样的芯片通信。

那么这里咱们使用什么代码演示呢?

演示的话,依然使用软件模拟IIC时序,管脚还是PB4和PB5。为什么不用硬件?因为我个人曾经做过一些简单的测试,硬件IIC使用的时候相对不是很稳定。当然,这不是说人家有问题,而是使用时的注意事项比较多,对于新手来说,建议从IO模拟开始。掌握熟练以后,可以根据需要换成硬件。

同时,这里同时提供了软件和硬件的代码供大家下载。根据文章结尾的提示就可以找到下载的位置。

好,这里咱们看一个例子,使用普通IO模拟IIC接口,和AT24C02通信,并且把主要信息打印到串口上。代码如下:

/* Includes ------------------------------------------------------------------*/
#include "stm8s.h"
#include "stm8_uart.h"
//#include <stdio.h>
#include "IIC_CONFIG.h"
/* Private defines -----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void Delay(uint16_t nCount)
{
  /* Decrement nCount value */
  while (nCount != 0)
  {   
    nCount--;
  }
}
void main(void)
{
  unsigned char a = 0;
  unsigned int b = 0;
  CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV2);
  I2CC_Init();
  Init_UART1();
  write_24c02(0x10,0x25);
  for(b = 0; b < 10000; b++);   //必须要有一个延时
  a = read_24c02(0x10);
  UART1_SendData8(a);
  while(1);
  
}

可以看到,主函数里进行了几个操作:

1、系统时钟设置为8MHZ。

2、相关GPIO初始化,软件模拟IIC时序。

3、串口初始化,后面讲串口。

4、在24C02的0x10位置写入数据0x25.

5、延时一段时间,读和写之间必须要隔一段时间,否则会出错。

6、读24C02的0x10位置的数据,并通过串口打印出来。

IIC接口的初始化,读操作、写操作,我都放在了一个C文件里,咱们直接看一下就醒了,有IIC操作经验的人,看一眼就懂了。

#include "IIC_CONFIG.h"

#define SCL_L              GPIO_WriteLow(GPIOB, GPIO_PIN_4)
#define SCL_H              GPIO_WriteHigh(GPIOB, GPIO_PIN_4)
#define SDA_L              GPIO_WriteLow(GPIOB, GPIO_PIN_5)
#define SDA_H              GPIO_WriteHigh(GPIOB, GPIO_PIN_5)

#define SDAM             GPIO_ReadInputPin(GPIOB, GPIO_PIN_5)
#define SET_SCL_OUT()    {GPIO_Init(GPIOB, GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_SLOW);}
#define SET_SDA_OUT()    {GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_PP_HIGH_SLOW);}
#define SET_SDA_IN()     {GPIO_Init(GPIOB, GPIO_PIN_5, GPIO_MODE_IN_FL_NO_IT);}

//--------------------------------------------------------------
// Prototype      : void I2C_Start(void)
// Calls          : Delay_5us()
// Description    : Start Singnal
//--------------------------------------------------------------
void I2CC_Init(void)
{
   //I2C_CR1 &= 0xFE;      //  PE=0, disable I2C module  
   SET_SCL_OUT();
   SET_SDA_OUT();   
}


//--------------------------------------------------------------
// Prototype      : void Delay_5us(void)
// Description    : 大约延时5us
//--------------------------------------------------------------
void Delay_5us(void)
{
   unsigned char i;                   //fcpu 8MHz 时
   for (i=20; i>0; i--);
}


//--------------------------------------------------------------
// Prototype      : void I2C_Start(void)
// Calls          : Delay_5us()
// Description    : Start Singnal
//--------------------------------------------------------------
void I2C_Start(void)
{
    // SDA 1->0 while SCL High
    SDA_H;                    
    SCL_H;                    
    Delay_5us();                
    SDA_L;                   
    Delay_5us();                
    SCL_L;                    
}


//--------------------------------------------------------------
// Prototype      : void I2C_Stop(void)
// Calls          : Delay_5us()
// Description    : Stop Singnal
//-------------------------------------------------------------- 
void I2C_Stop(void)
{
    // SDA 0->1 while SCL High
    SDA_L;                   
    SCL_H;                   
    Delay_5us();                
    SDA_H;                   
    Delay_5us();               
}

//--------------------------------------------------------------
// Prototype      : void I2C_SendACK(uchar ack);
// Calls          : Delay_5us()
// Parameters     : bit ack:1-noack, 0-ack
// Description    : Master device send ACK to slave device.
//--------------------------------------------------------------
void I2C_SendACK(uchar ack)
{
    if(ack == 0)
    {
      SDA_L; 
    }  
    else
    {
      SDA_H; 
    }
            
    SCL_H;                   
    Delay_5us();  
    
    SCL_L;                    
    Delay_5us();     
}

//--------------------------------------------------------------
// Prototype      : uchar I2C_SendByte(uchar sendDAT)
// Calls          : Delay_5us()
// Parameters     : uchar sendDAT---data to be send
// Return Value   : CY--slave ack (1---noack,0---ack)
// Description    : Send one byte to I2C
//--------------------------------------------------------------
uchar I2C_SendByte(uchar sendDAT)
{
    uchar i,revack;

    for (i= 0 ; i< 8; i++)         
    {
     SCL_L;                
     Delay_5us();  

       if (sendDAT & 0x80)             // write data
       {
          SDA_H;
       }
       else   
       {
          SDA_L;
       }

        sendDAT <<=  1;

        SCL_H;                
        Delay_5us();     
    } 
 

   SCL_L;                
   Delay_5us();  
   
   SET_SDA_IN();
   
   SCL_H;    
   asm("nop");
   asm("nop");
 
   revack = (uchar)SDAM;
        
   Delay_5us();   
   SCL_L;   
      
   SET_SDA_OUT();
   
   Delay_5us();  

   return revack;
}


//--------------------------------------------------------------
// Prototype      : uchar I2C_RecvByte()
// Calls          : Delay_5us()
// Parameters     : none
// Return Value   : revDAT- received data
// Description    : Receive one byte from I2C
//--------------------------------------------------------------
uchar I2C_RecvByte()
{
    uchar i;
    uchar revDAT = 0;
    
    SDA_H;     // latch the Data port befor reading
    
    SET_SDA_IN();
    
    for (i=0; i<8; i++)         
    { 
       revDAT <<= 1;
        
       SCL_H; 
       
       asm("nop");
       asm("nop");
       
       if (SDAM)
       {
          revDAT |= 0x01;
       }
       else
       {
          revDAT &= 0xfe;
       }
       Delay_5us(); 
       SCL_L;                
       Delay_5us();  
    }
   SET_SDA_OUT();
   
   return revDAT;
}


//--------------------------------------------------------------
// Prototype      : void Write_PT2314(uchar wdata)
// Calls          : I2C_Start(), I2C_Stop(),I2C_SendByte()
// Parameters     : RegAddr-- target memory address,  
//                  wrdata--- data to be writing
// Description    : Write one byte to target memory
//--------------------------------------------------------------
void write_24c02(uchar regadd,uchar wdata)
{
    I2C_Start();            
    I2C_SendByte(SlaveAddress);     // Device Addr + Write (operation) 
    I2C_SendByte(regadd); 
    I2C_SendByte(wdata);     
    I2C_Stop();             
}

u8 read_24c02(uchar regadd)
{
    u8 revdata;
    
    I2C_Start();            
    I2C_SendByte(SlaveAddress);     // Device Addr + Write (operation)   
    I2C_SendByte(regadd); 
    
    I2C_Start();    
    I2C_SendByte(SlaveAddress+1);     // Device Addr + Write (operation)   
     
    revdata = I2C_RecvByte();    

    
    I2C_Stop();   
    
    return revdata;
}

最后,编译、下载、上电,上电之前记得把串口连到电脑上,波特率9600.就能看到串口打印的字符“a”,功能正常!

打完收工!

对了,虽然这里使用软件模拟的方式写的代码,但我们也写了硬件IIC的代码,想要获取该程序完整的工程文件,可以关注公众号:单片机爱好者,然后回复关键词:STM8S。可以获取完整的下载链接,里面包含工程文件、视频、PPT、数据手册等所有相关资料。

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据