欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

STM8S003F3P6采集DS18B20数码管显示 串口通讯

程序员文章站 2022-03-11 15:40:19
功能介绍:STM8S003F3P6使用单总线方式和DS18B20建立简单的通讯、DS18B20反馈温度值,数码管显示温度值无小数,利用串口命令可以设置数码管亮灭,温度值上传周期等等。具体以协议为准。程序源码在一个资源里面,下载需要积分,没有积分的可以私信我。https://download.csdn.net/download/L_e_c/13187959硬件设计:如下图,一个单片机预留烧录口,两位共阴数码管,数码管在原理图中省略了,一路DS18B20接上拉之后到芯片引脚。一路UART可直接通过U...

功能介绍:

STM8S003F3P6使用单总线方式和DS18B20建立简单的通讯、DS18B20反馈温度值,数码管显示温度值无小数,利用串口命令可以设置数码管亮灭,温度值上传周期等等。具体以协议为准。程序源码在一个资源里面,下载需要积分,没有积分的可以私信我。https://download.csdn.net/download/L_e_c/13187959

硬件设计:

如下图,一个单片机预留烧录口,两位共阴数码管,数码管在原理图中省略了,一路DS18B20接上拉之后到芯片引脚。一路UART可直接通过USB转TTL模块连接电脑调试。

STM8S003F3P6采集DS18B20数码管显示 串口通讯

软件设计:

1)主程序设计

初始化芯片内部flash(给串口命令保存参数用,)初始化IO口(数码管段选及位选),DS18B20初始化,定时器(定时1ms,给主程序做时基用),初始化串口,打开中断。大循环里以Auto_Flag变量分三个方式,程序看明白了其实没有太大的区别;然后就是串口接收到协议相应的命令,给一些标志位置位,然后在大循环里应答,不占用中断时间;system1ms是1ms的时基,显示刷新周期是2*4ms;再往后就是500ms采集一次温度值然后给显示数组赋值(在这里处理的正负温度值),数码管的亮灭也是在500ms的时基里处理的;再下面的Usart1_Rev_flag变量是确定直接返回温度值还是周期返回温度值;后面几乎相同,废话不说,直接贴程序。

int main(void)
{
  u8 state=0;
  u8 cclen=0;
//   u16 Cnt_500ms=0;
   u16 Cnt_2S=0;
   u8 SendCnt_xS=0;
   u8 Cnt_10ms=0;
   
  /*设置内部高速时钟16M为主时钟*/ 
   CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
   FLASH_Initializes();
   
  /*!<Set High speed internal clock */
   delay_init(16);
   
   LED_Init();
   Init_DS18B20();
   Tim1_Init();
   SetLedOFF(); 
    GPIO_Init(GPIOD, GPIO_PIN_5, GPIO_MODE_OUT_OD_LOW_FAST);         
    GPIO_Init(GPIOD, GPIO_PIN_6, GPIO_MODE_IN_PU_NO_IT); 
   Uart_Init();
   
  __enable_interrupt(); 
  delay_ms(100);
  Data_Init();
//  UART1_SendString("Serial Communication ---STM8 Development Board of FengChi Electron ",\
//             sizeof("Serial Communication ---STM8 Development Board of FengChi Electron"));
  Led_Temp[0]=11;
  Led_Temp[1]=11;
  if(Auto_Flag==0){
    Usart1_Rev_Cot_flag=0;
  }
  else if(Auto_Flag==1)
  {
    Usart1_Rev_Cot_flag=1;
  }
  else if(Auto_Flag==2)
  {
    Usart1_Rev_Cot_flag=1;
    SendTime_Num=1;
  }
  
  
  while (1)
  { 
    if(Auto_Flag==0){
        if (SendTime_Flag==1)
        {
          SendTime_Flag=0;
          UART1_SendString("ok\r\n",4);
        }
        if(SendAuto_Flag==1){
          SendAuto_Flag=0;
          UART1_SendString("ok\r\n",4);
        }
        if(system1ms==1)
        {
          system1ms=0;
          if(++Cnt_10ms>=2)
          {
            Cnt_10ms=0;
            switch (state)
            {
              case 0 :{
                state = 1;
                Assembly_2(~0X00);
                Assembly_8(~seg7[Led_Temp[0]]);
                Assembly_2(~0X01);
              }break;
              case 1 :{
                state = 2;
                Assembly_2(~0X00);
                Assembly_8(~seg7[Led_Temp[1]]);
                Assembly_2(~0X02);
              }break;
              case 2 :{
                state = 3;
                Assembly_2(~0X00);
                Assembly_8(~seg7[Led_Temp[0]]);
                Assembly_2(~0X01);
                Temptrue=Read_DS18B20();
              }break;
              case 3 :{
                state = 0;
                Assembly_2(~0X00);
                Assembly_8(~seg7[Led_Temp[1]]);
                Assembly_2(~0X02);
              }break;
              default: state = 0;
              break;
            }
          } 
          if(++Cnt_2S>=500)
          {
              Cnt_2S=0;
              if(Temptrue>=0){
                cclen=sprintf(Send_Server,"Temptrue=%02d.%01d;\r\n",Temptrue/10,Temptrue%10);
                Led_Temp[0]=Temptrue/100+12;  
                Led_Temp[1]=Temptrue/10%10;
              }
              else
              {
                cclen=sprintf(Send_Server,"Temptrue=-%02d.%01d;\r\n",(0-Temptrue)/10,(0-Temptrue)%10);
                if((0-Temptrue)>199) Led_Temp[0]=(0-Temptrue)/100+12;  
                else if((0-Temptrue)>99)  Led_Temp[0]=11+14;
                else Led_Temp[0]=11+13;
                                    Led_Temp[1]=(0-Temptrue)/10%10+12;
              }
              if(Usart1_Rev_Cot_flag==0)
              {
                Led_Temp[0]=11;
                Led_Temp[1]=11;
                Temptrue=Read_DS18B20();
              }
              
          }
        }  
        if(Usart1_Rev_flag==1){
          Usart1_Rev_flag=0;
          UART1_SendString(Send_Server,cclen);
        }
        else {
          if(system1S==1){
            system1S=0;
            if(SendTime_Num!=0){
              if(++SendCnt_xS>=SendTime_Num){
                SendCnt_xS=0;
                UART1_SendString(Send_Server,cclen);
              }
            }
          }
        }
      
    }else if(Auto_Flag==1){
      if (SendTime_Flag==1)
        {
          SendTime_Flag=0;
          UART1_SendString("ok\r\n",4);
        }
        if(SendAuto_Flag==1){
          SendAuto_Flag=0;
          UART1_SendString("ok\r\n",4);
        }
        if(system1ms==1)
        {
          system1ms=0;
          if(++Cnt_10ms>=2)
          {
            Cnt_10ms=0;
            switch (state)
            {
              case 0 :{
                state = 1;
                Assembly_2(~0X00);
                Assembly_8(~seg7[Led_Temp[0]]);
                Assembly_2(~0X01);
              }break;
              case 1 :{
                state = 2;
                Assembly_2(~0X00);
                Assembly_8(~seg7[Led_Temp[1]]);
                Assembly_2(~0X02);
              }break;
              case 2 :{
                state = 3;
                Assembly_2(~0X00);
                Assembly_8(~seg7[Led_Temp[0]]);
                Assembly_2(~0X01);
                Temptrue=Read_DS18B20();
              }break;
              case 3 :{
                state = 0;
                Assembly_2(~0X00);
                Assembly_8(~seg7[Led_Temp[1]]);
                Assembly_2(~0X02);
              }break;
              default: state = 0;
              break;
            }
          } 
          if(++Cnt_2S>=500)
          {
              Cnt_2S=0;
              if(Temptrue>=0){
                cclen=sprintf(Send_Server,"Temptrue=%02d.%01d;\r\n",Temptrue/10,Temptrue%10);
                Led_Temp[0]=Temptrue/100+12;  
                Led_Temp[1]=Temptrue/10%10;
              }
              else
              {
                cclen=sprintf(Send_Server,"Temptrue=-%02d.%01d;\r\n",(0-Temptrue)/10,(0-Temptrue)%10);
                if((0-Temptrue)>199) Led_Temp[0]=(0-Temptrue)/100+12;  
                else if((0-Temptrue)>99)  Led_Temp[0]=11+14;
                else Led_Temp[0]=11+13;
                                    Led_Temp[1]=(0-Temptrue)/10%10+12;
              }
              if(Usart1_Rev_Cot_flag==0)
              {
                Led_Temp[0]=11;
                Led_Temp[1]=11;
                Temptrue=Read_DS18B20();
              }
              
          }
        }  
        if(Usart1_Rev_flag==1){
          Usart1_Rev_flag=0;
          UART1_SendString(Send_Server,cclen);
        }
        else {
          if(system1S==1){
            system1S=0;
            if(SendTime_Num!=0){
              if(++SendCnt_xS>=SendTime_Num){
                SendCnt_xS=0;
                UART1_SendString(Send_Server,cclen);
              }
            }
          }
        }
      }
    else if(Auto_Flag==2){
      if (SendTime_Flag==1)
        {
          SendTime_Flag=0;
          UART1_SendString("ok\r\n",4);
        }
        if(SendAuto_Flag==1){
          SendAuto_Flag=0;
          UART1_SendString("ok\r\n",4);
        }
        if(system1ms==1)
        {
          system1ms=0;
          if(++Cnt_10ms>=2)
          {
            Cnt_10ms=0;
            switch (state)
            {
              case 0 :{
                state = 1;
                Assembly_2(~0X00);
                Assembly_8(~seg7[Led_Temp[0]]);
                Assembly_2(~0X01);
              }break;
              case 1 :{
                state = 2;
                Assembly_2(~0X00);
                Assembly_8(~seg7[Led_Temp[1]]);
                Assembly_2(~0X02);
              }break;
              case 2 :{
                state = 3;
                Assembly_2(~0X00);
                Assembly_8(~seg7[Led_Temp[0]]);
                Assembly_2(~0X01);
                Temptrue=Read_DS18B20();
              }break;
              case 3 :{
                state = 0;
                Assembly_2(~0X00);
                Assembly_8(~seg7[Led_Temp[1]]);
                Assembly_2(~0X02);
              }break;
              default: state = 0;
              break;
            }
          } 
          if(++Cnt_2S>=500)
          {
              Cnt_2S=0;
              if(Temptrue>=0){
                cclen=sprintf(Send_Server,"Temptrue=%02d.%01d;\r\n",Temptrue/10,Temptrue%10);
                Led_Temp[0]=Temptrue/100+12;  
                Led_Temp[1]=Temptrue/10%10;
              }
              else
              {
                cclen=sprintf(Send_Server,"Temptrue=-%02d.%01d;\r\n",(0-Temptrue)/10,(0-Temptrue)%10);
                if((0-Temptrue)>199) Led_Temp[0]=(0-Temptrue)/100+12;  
                else if((0-Temptrue)>99)  Led_Temp[0]=11+14;
                else Led_Temp[0]=11+13;
                                    Led_Temp[1]=(0-Temptrue)/10%10+12;
              }
              if(Usart1_Rev_Cot_flag==0)
              {
                Led_Temp[0]=11;
                Led_Temp[1]=11;
                Temptrue=Read_DS18B20();
              }
              
          }
        }  
        if(Usart1_Rev_flag==1){
          Usart1_Rev_flag=0;
          UART1_SendString(Send_Server,cclen);
        }
        else {
          if(system1S==1){
            system1S=0;
            if(SendTime_Num!=0){
              if(++SendCnt_xS>=SendTime_Num){
                SendCnt_xS=0;
                UART1_SendString(Send_Server,cclen);
              }
            }
          }
        }
      } 
    
  }
}

2)DS18B20.c

编写该程序只需要记住一点,一定要和时序对应起来;首先要留意延时函数,往往延时函数是导致和18B20通讯不成功的主要因素。其他就没有太多要说的了,看源码。

#include "ds18b20.h"

u16 temp=0;
s16 Temptrue=0;

/* Private functions ---------------------------------------------------------*/
/* Public functions ----------------------------------------------------------*/
void Alarm_for_No_DS18B20(void)
{
    //单总线上没有发现DS18B20则报警,该动作据具体应用具体处理
}
//---------------------------------------------------------------------
unsigned char DS18B20_Start(void) //复位ds18b20芯片
{
    unsigned char i,succ=0xff;
    DS18B20_PIN_SET_OUT(); //置为输出口
    DS18B20_WR0();          //总线产生下降沿,初始化开始
    // for(i=0; i<30; i++)delay_us(25); //总线保持低电平在480 - 960微秒之间  ;i<20;(25us)
    delay_us(500);
    DS18B20_WR1();         //总线拉高
    DS18B20_PIN_SET_IN();  //置为输入,主机释放总线,准备接收DS18B20的应答脉冲
    i=0;
    while(R_DS18B20())         //等待DS18B20发出应答脉冲
    {
        delay_us(5);          //5
        if(++i>12)            //DS18B20检测到总线上升沿后等待15-60us
        {
            succ=0x00;           //如果等待大于约60us,报告复位失败
            break;
        }
    }
    i=0;
    while(!R_DS18B20())       //DS18B20发出存在脉冲,持续60-240us
    {
        delay_us(5);         //5
        if(++i>48)            //如果等带大于约240us,报告复位失败
        {
            succ=0x00;
            break;
        }
    }
    delay_us(20);
    return succ;
}
//---------------------------------------------------------------------
void DS18B20_SendU8(unsigned char d8)//向DS18B20写一字节函数
{
    unsigned char i;
    DS18B20_PIN_SET_OUT();   //置为输出口
    for(i=0; i<8; i++)
    {
        DS18B20_WR0();       //总线拉低,启动“写时间片”
        delay_us(2);            //大于1微妙
        if(d8&0x01)DS18B20_WR1();
        delay_us (32);      //延时至少60微秒,使写入有效
        delay_us (30);
        DS18B20_WR1();       //总线拉高,释放总线,准备启动下一个“写时间片”
        d8>>=1;
        delay_us (1);
    }
    DS18B20_PIN_SET_IN();   //主机释放总线
}
//---------------------------------------------------------------------
unsigned char DS18B20_ReadU8(void)//从DS18B20读1个字节函数
{
    unsigned char i,d8;
    for(i=0; i<8; i++)
    {
        d8>>=1;
        DS18B20_PIN_SET_OUT();//置为输出口
        DS18B20_WR0();        //总线拉低,启动读“时间片”
        delay_us(2);         //大于1微妙
        DS18B20_WR1();        //主机释放总线,接下来(2~15)us内读有效
        DS18B20_PIN_SET_IN(); //引脚设定为输入口,准备读取
        delay_us(2);         //延时2个us后进行读


        if(R_DS18B20())d8|=0x80;//从总线拉低时算起,约15微秒内读取总线数据
        delay_us(32);       //60us后读完成
        delay_us(30);
        DS18B20_WR1();       //总线拉高,主机释放总线,准备启动下一个“写时间片”
    }
    DS18B20_PIN_SET_IN();    //主机释放总线
    return(d8);
}
//------------------------------------------------------------------------------------
void Init_DS18B20(void)           //初始化DS18B20
{
    unsigned char i;
    i=DS18B20_Start();             //复位
    if(!i)                          //单总线上没有发现DS18B20则报警
    {
        Alarm_for_No_DS18B20();
        return;
    }
    DS18B20_SendU8 (SKIP_ROM);  //跳过rom匹配
    DS18B20_SendU8 (WRITE_RAM); //设置写模式
    DS18B20_SendU8 (0x64);        //设置温度上限100摄氏度
    DS18B20_SendU8 (0x8a);        //设置温度下线-10摄氏度
    DS18B20_SendU8 (0x7f);        //12bit(默认)
}


//--------------------------------------------------------------------------------------

unsigned char tl;
    unsigned int  th;
unsigned int Read_DS18B20(void)  //读取并计算要输出的温度
{
    unsigned char i;
    
    i=DS18B20_Start();           //复位
    if(!i)                        //单总线上没有发现DS18B20则报警
    {
        Alarm_for_No_DS18B20();
        return 0;
    }
    // delay_ms(1);
    DS18B20_SendU8(SKIP_ROM);     //发跳过序列号检测命令
    DS18B20_SendU8(CONVERT_TEM); //命令Ds18b20开始转换温度
    i=0;
    // delay_ms(1);
    while(!R_DS18B20())       //当温度转换正在进行时,主机读总线将收到0,转换结束为1
    {
        delay_ms(2);
        if(++i>250) break;              //至多转换时间为750ms
    }
    DS18B20_Start();                 //初始化
    // delay_ms(1);
    DS18B20_SendU8(SKIP_ROM);    //发跳过序列号检测命令
    DS18B20_SendU8(READ_RAM);  //发读取温度数据命令
    tl=DS18B20_ReadU8();           //先读低8位温度数据
    th=DS18B20_ReadU8()<<8;        //再读高8位温度数据
    if((th&0xf000)==0xf000)   
      return -((0-(th|tl))*10>>4);
    else 
      return (th|tl)*10>>4;              //温度放大了10倍,*0.0625=1/16=>>4
}


3)其他

内部Flash操作和UART操作,就是一些配置,熟悉库操作就可以,串口接收中断可以看一下处理方式(状态机),后续可以考虑使用帧中断,之后在其他博客会分享。

4)协议、硬件及调试效果

STM8S003F3P6采集DS18B20数码管显示 串口通讯

STM8S003F3P6采集DS18B20数码管显示 串口通讯STM8S003F3P6采集DS18B20数码管显示 串口通讯

总结:

博客就只是分享了原理图和程序,一些注释也不全。第一个分享,难免有不对之处,欢迎指正交流,谢谢。

本文地址:https://blog.csdn.net/L_e_c/article/details/110124651