• 基于STC12C5A60S2系列1T 8051单片机实现一主单片机与一从单片机相互发送数据的RS485通信功能


    基于STC12C5A60S2系列1T 8051单片机实现一主单片机与一从单片机相互发送数据的RS485通信功能的RS485通信功能

    STC12C5A60S2系列1T 8051单片机管脚图

    在这里插入图片描述在这里插入图片描述# STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置在这里插入图片描述# STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍在这里插入图片描述在这里插入图片描述

    STC12C5A60S2系列1T 8051单片机串口通信介绍

    在这里插入图片描述在这里插入图片描述在这里插入图片描述

    STC12C5A60S2系列1T 8051单片机串口通信的结构

    基于STC12C5A60S2系列1T 8051单片机串口通信的特殊功能寄存器列表

    在这里插入图片描述

    基于STC12C5A60S2系列1T 8051单片机串口通信用到的特殊功能寄存器

    STC12C5A60S2系列1T 8051单片机辅助寄存器AUXR

    在这里插入图片描述
    作用:用来设置STC12C5A60S2系列1T 8051单片机串口通信类型、波特率

    STC12C5A60S2系列1T 8051单片机辅助寄存器AUXR1

    在这里插入图片描述
    作用:用来设置STC12C5A60S2系列1T 8051单片机串口通信引脚切换

    串口1控制寄存器SCON

    在这里插入图片描述
    作用:用来设置STC12C5A60S2系列1T 8051单片机串口通信以下功能
    (1)、设置串口通信工作模式
    (2)、设置串口方式2或方式3多机通信
    (3)、设置串口通信允许接收
    (4)、设置串口通信在方式2或方式3下发送第9位数据
    (5)、设置串口通信通信在方式2或方式3下接收第9位数据
    (6)、设置串口通信发送中断请求
    (7)、设置串口通信接收中断请求

    串口电源控制寄存器PCON

    在这里插入图片描述
    作用:用来设置STC12C5A60S2系列1T 8051单片机串口通信以下功能
    (1)、设置串口通信波特率选择
    (2)、设置串口通信帧错误检测有效控制

    串口数据缓冲寄存器SBUF

    在这里插入图片描述在这里插入图片描述
    作用:用来设置STC12C5A60S2系列1T 8051单片机串口通信发送或接收数据

    串口辅助寄存器AUXR

    在这里插入图片描述在这里插入图片描述
    作用:用来设置STC12C5A60S2系列1T 8051单片机串口通信类型、波特率

    串口中断寄存器

    在这里插入图片描述
    作用:用来设置STC12C5A60S2系列1T 8051单片机串口通信中断允许、中断优先级

    基于STC12C5A60S2系列1T 8051单片机串口1通信工作模式

    串口1通信模式0

    在这里插入图片描述

    串口1通信模式1

    在这里插入图片描述在这里插入图片描述

    串口1通信模式2

    在这里插入图片描述在这里插入图片描述

    串口1通信模式3

    在这里插入图片描述在这里插入图片描述

    串口通信波特率设置

    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

    基于STC12C5A60S2系列1T 8051单片机实现一主单片机与一从单片机相互发送数据的RS485通信功能介绍

    串口通信简单介绍

    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

    基于STC12C5A60S2系列1T 8051单片机实现一主单片机与一从单片机相互发送数据的RS485通信功能电路连接及工作原理

    USB转RS485 取到A B电平

    在这里插入图片描述

    TTL转RS485 取到A B电平作为逻辑电平

    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述

    基于STC12C5A60S2系列1T 8051单片机实现一主单片机与一从单片机相互发送数据的RS485通信功能编程

    主单片机

    main.c

    #include <stc12c5a60s2.h>
    #include "Uart.h"
    #include "Timer0.h"
    #include "Key.h"
    #include "Digitron.h"
    #include "stdio.h"
    #define uchar unsigned char//自定义无符号字符型为uchar
    #define uint unsigned int//自定义无符号整数型为uint 
    sbit LED = P1^7;//声明单片机P1.7端口为LED接口
     void PortModeSet()//端口模式设置函数
    {
       
      P0M1 = 0x00;
      P0M0 = 0x00;
      P1M1 = 0x00;
      P1M0 = 0x00;
      P2M1 = 0x00;
      P2M0 = 0x00;
      P3M1 = 0x00;
      P3M0 = 0x00;
      P4M1 = 0x00;
      P4M0 = 0x00;
     }
     void main()//主函数
    {
       
      PortModeSet();//端口模式设置函数
      Uart1Init();//串行口1工作模式1的8位串行口波特率可变初始化函数 波特率为9600bps 晶振为12MHz
      Timer0Init();//定时器0的16位定时模式1用12分频定时2ms初始化函数 晶振为12MHz
      DigitronBootDisplay();//数码管开机显示函数
      while(1)//主循环
     {
        
       KeyScanResult();//按键扫描结果函数
    //   if(ReceiveOverDataFlag == 1)//判断接收完数据标志位变量是否置1 即主单片机串行口数据缓存器已经接收完从单片机发送来的数据
    //  {
       
    //    ReceiveOverDataFlag = 0;//接收完数据标志位变量清0
    //	LED = 0;//点亮LED灯 表示主单片机成功接收从单片机发送来的数据
    //	RS485DIR = 1;//启动RS485发送数据控制
    //	KeyPressNumber = ReceiveData;//接收数据变量含有的数值赋给按键按下数值变量 即主单片机串行口数据缓存器接收从单片机发送来的数据赋给按键按下数值变量
    //    RS485DIR = 1;//启动RS485发送数据控制
    //    ReceiveData = ReceiveData + 1;//接收数据变量累加
    //    MasterSendData(ReceiveData);//主单片机发送数据函数 即主单片机给从单片机发送数据
    //    RS485DIR = 0;//启动RS485接收数据控制 准备下一次收发数据循环
    //   }
      }
     }
    

    Uart.c

    /*****关于8051系列单片机定时器溢出率、波特率和定时器初值(定时计数初值)之间计算的知识点*****/
    /****
    一、定时器溢出率计算公式
    1、定时器溢出率:定时器每秒溢出的次数
    2、定时器溢出率计算公式表
        定时方式           分频方式                      公式
    方式1:16位定时器  12分频(即12T 默认值)  Ft=晶振频率/12/(65536-定时器初值)
    方式2:8位定时器   12分频(即12T 默认值)  Ft=晶振频率/12/(256-定时器初值)
    方式1:16位定时器      1分频(即1T)      Ft=晶振频率/1/(65536-定时器初值)
    方式2:8位定时器       1分频(即1T)      Ft=晶振频率/1/(256-定时器初值)
    二、波特率计算公式
    1、波特率:每秒传输二进制位数的多少
    2、波特率计算公式表
        定时方式             分频方式                        公式
    方式1:16位定时器T1  12分频(即12T 默认值)  波特率=晶振频率/12/(65536-定时器初值)/4
    方式2:8位定时器T1   12分频(即12T 默认值)  波特率=晶振频率/12/(256-定时器初值)*2^SMOD/32
    方式1:16位定时器T2  12分频(即12T 默认值)  波特率=晶振频率/12/(65536-定时器初值)/4
    方式1:16位定时器T1      1分频(即1T)      波特率=晶振频率/1/(65536-定时器初值)/4
    方式2:8位定时器T1       1分频(即1T)      波特率=晶振频率/1/(256-定时器初值)*2^SMOD/32
    方式1:16位定时器T2      1分频(即1T)      波特率=晶振频率/1/(65536-定时器初值)/4
    三、根据波特率计算定时器初值(定时器定时计数)
        定时方式             分频方式                        公式
    方式1:16位定时器T1  12分频(即12T 默认值)  定时器初值(定时计数)=65536-晶振频率/(48*波特率)
    方式2:8位定时器T1   12分频(即12T 默认值)  定时器初值(定时计数)=256-晶振频率*2^SMOD/(384*波特率)
    方式1:16位定时器T2  12分频(即12T 默认值)  定时器初值(定时计数)=65536-晶振频率/(48*波特率)
    方式1:16位定时器T1      1分频(即1T)      定时器初值(定时计数)=65536-晶振频率/(4*波特率)
    方式2:8位定时器T1       1分频(即1T)      定时器初值(定时计数)=256-晶振频率*2^SMOD/(32*波特率)
    方式1:16位定时器T2      1分频(即1T)      定时器初值(定时计数)=65536-晶振频率/(4*波特率)
    *****/
    #include "Uart.h"
    #include "stdio.h"
    #define	uchar unsigned char	//定义无符号字符
    #define	uint  unsigned int	//定义无符号整形
    //bit ReceiveOverDataFlag = 0;//定义接收完数据标志位变量为0
    uchar ReceiveData = 0;//定义接收数据变量为0
     void Uart1Init()//串行口1工作模式1的8位串行口波特率可变初始化函数 波特率为9600bps 晶振为12MHz
    {
       
      SCON = 0x50;//工作模式1的8位串行口波特率可变
      AUXR &= 0xBF;//定时器时钟12T模式
      AUXR &= 0xFE;//串口1选择定时器1为波特率发生器
      PCON &= 0x7f;//波特率不加倍
      TMOD &= 0x0f;//定时器/计数器工作模式清0
      TMOD |= 0x20;//设定定时器/计数器为定时器 工作模式为8位自动重装定时器1模式2
      TH1 = 0xfd;//设定定时器1高八位初值
      TL1 = 0xfd;//设定定时器1低八位初值
      ET1 = 0;//禁止定时器1中断
      ES = 1;//允许串行口1中断
      EA = 1;//开总中断
      TR1 = 1;//打开定时器1
      RS485DIR = 0;//启动RS485接收数据控制
     }
    
     void MasterSendData(uint Data)//主单片机发送数据函数 即主单片机给从单片机发送数据
    {
       
      RS485DIR = 1;//启动RS485发送数据控制
      SBUF = Data;//把数据变量Data含有数据写入主单片机数据缓存器 主单片机数据缓存器会把数据变量Data含有数据发送给从单片机数据缓存器
      while(!TI);//当数据发送结束标志位变量TI为0 表示数据还没发送完 若数据发送结束标志位变量TI为1 表示数据已发送完 从而触发串口中断 最后需在串口中断程序中或者在其他程序中把数据发送结束标志位变量TI清0 才能进行下一次发送
      TI = 0;//数据发送结束标志位变量TI清0
      RS485DIR = 0;//启动RS485接收数据控制
     }
    
    // uint ReceiveData()//接收数据函数 即主单片机接收从单片机发送来的数据
    //{
       
    //  uint Data;//
    //	Data = SBUF;//把数据Data写入主单片机数据缓存器 主单片机数据缓存器会把数据Data发送给从单片机数据缓存器
    //  while(!RI)//当数据发送结束标志位变量TI为0 表示数据还没发送完 若数据发送结束标志位变量TI为1 表示数据已发送完 从而触发串口中断 最后需在串口中断程序中或者在其他程序中把数据发送结束标志位变量TI清0 才能进行下一次发送
    //  RI = 0;//数据发送结束标志位变量TI清0
    //	ReceiveOverDataFlag = 1;//接收完数据标志位变量置1
    //	return Data;//
    // }
     
    // void SendString(uint *Data)//发送字符串函数
    //{
       
    //  while(*Data != '\0')//判断字符串是否已发送完成 当*Data = '\0'表示字符串已发送完成
    // {
       
    //   SendData(*Data++);//循环发送字符串中每个字符
    // }
    //}
    
     void Uart1() interrupt 4//串口1通信中断函数
    {
       
      if(RI)//判断单片机串行口数据缓存器是否接收完数据 当RI为1 表示主单片机串行口数据缓存器已经接收完从单片机发送来的数据
     {
       
       ReceiveData = SBUF;//读取单片机串行口数据缓存器中的数据赋给接收数据变量 即主单片机串行口缓存寄存器通过串行口通信接收从单片机发送来的数据
       RI = 0;//单片机串行口接收数据结束标志位清0
    //   ReceiveData = ReceiveData + 1;//接收数据变量累加
    //   SBUF = ReceiveData;//把接收数据变量包含的数据赋给单片机串行口数据缓存器 即单片机通过串行口通信把来自计算机串口调试助手软件从发送区发送来的数据发回给计算机串口调试助手软件接收区显示出来
    //   ReceiveOverDataFlag = 1;//接收完数据标志位变量置1
      }
     }
    

    Uart.h

    #ifndef  _UART_H
    #define  _UART_H
    #include "STC12C5A60S2.h"
    #define uchar unsigned char//自定义无符号字符型为uchar
    #define uint unsigned int//自定义无符号整数型为uint
    sbit RS485DIR = P1^6;//声明RS485收发数据控制端口 RS485DIR = 0为接收状态 RS485DIR = 1为发送状态
    //extern bit ReceiveOverDataFlag;//声明接收完数据标志位变量
    extern uchar ReceiveData;//声明接收数据变量
    void Uart1Init();//串行口1工作模式1的8位串行口波特率可变初始化函数 波特率为9600bps 晶振为12MHz
    extern void MasterSendData(uint Data);//主单片机发送数据函数 即主单片机给从单片机发送数据
    //extern uint ReceiveData();//接收数据函数 即主单片机接收从单片机发送来的数据
    //void SendString(uint *Data);//发送字符串函数
    #endif 
    

    Key.c

    #include "Key.h"
    #include "Uart.h"
    #include "Timer0.h"
    #define	uchar unsigned char	//定义无符号字符
    #define	uint  unsigned int	//定义无符号整形
    #define KeyPressDeshakeTime 15//自定义按键按下消抖时间为20ms	
    #define KeyLongPressDelayTime 100//自定义按键长按延时时间为200ms
    //uchar ClearKeyPressFlag = 0;//定义清零按键按下标志位变量为0
    //uchar SetKeyFlag = 0;//定义设置按键标志位变量为0
    //uchar SetKeyPressCountFlag = 1;//定义设置按键按下计数标志位变量为1
    //uchar SetKeyShortPressLcokFlag = 0;//定义设置按键短按按下锁定标志位变量为0
    uchar AddKeyPressLcokFlag = 0;//定义增加按键锁定标志位变量为0
    uchar AddKeyShortPressLcokFlag = 0;//定义增加按键短按按下锁定标志位变量为0
    uchar AddKeyLongPressLcokFlag = 0;//定义增加按键长按按下锁定标志位变量为0
    uchar DecKeyPressLcokFlag = 0;//定义减少按键锁定标志位变量为0
    uchar DecKeyShortPressLcokFlag = 0;//定义减少按键短按按下锁定标志位变量为0
    uchar DecKeyLongPressLcokFlag = 0;//定义减少按键长按按下锁定标志位变量为0
    //uchar SetKeyShortPressCount = 0;//定义设置按键短按按下计数变量为0
    //uchar SetKeyShortPressFlag = 0;//定义设置按键短按按下标志位变量为0
    //uchar SetKeyShortPressCountFlag = 1;//定义设置按键短按按下计数标志位变量为1
    //uchar SetKeyLongPressLcokFlag = 0;//定义设置按键长按按下锁定标志位变量为0
    //uchar SetKeyLongPressCount = 0;//定义设置按键长按按下计数变量为0
    //uchar SetKeyLongPressFlag = 0;//定义设置按键长按按下标志位变量为0
    //uint  SetKeyLongPressCountFlag = 1;//定义设置按键长按按下计数标志位变量为0
    uint  KeyPressDelayTime = 0;//定义按键按下延时时间变量为0
    uint  KeyLiftDelayTime = 0;//定义按键弹起延时时间变量为0
    uint  KeyPressNumber0 = 0;//定义按键按下数值变量为0
    //uint  KeyPressNumberLcokFlag = 0;//定义按键按下数值锁定标志位变量为0
    //uint  KeyPressAddress = 0;//定义按键按下地址变量为0
    //uint  KeyPressAddressCount = 0;//定义按键按下地址计数变量为0
    uint  KeyType = 0;//定义按键类型变量为0
    //uchar KeyPressCount = 0;//定义按键按下计数变量为0
    //uchar MasterSendAddressFlag = 0;//定义主单片机发送通信地址标志位变量为0
    //uchar MasterSendDataFlag = 0;//定义主单片机发送数据标志位变量为0
    //  uint KeyScan ()//带按键返回值的按键扫描函数
      void KeyScan ()//按键扫描函数
    {
         	  
     
       if((AddKey == 0) && (AddKeyPressLcokFlag == 0))//增加按键按下
     {
       	  
    	DecKeyPressLcokFlag = 1;//减少按键按下锁定标志位变量置1 防止增加按键按下时 有减少按键按下 从而实现增加减少按键互不干扰
    	KeyPressDelayTime++;//按键按下延时时间变量自加
    	if((AddKeyShortPressLcokFlag == 0) && (AddKeyLongPressLcokFlag == 0))//增加按键短按按下锁定标志位变量为0与增加按键长按按下锁定标志位变量为0 一是为了增加按键第1次能短按 二是为了增加按键第1次短按后 如果不松手一直按着 会激活增加按键短按锁定标志位置1 跳出增加按键短按 进入增加按键长按 三是为了增加按键长按后松手 防止进入短按 从而实现短按与长按互不干扰 
      {
       	 
    	 if(KeyPressDelayTime > KeyPressDeshakeTime)//判断按键按下延时时间变量是否大于按键按下消抖时间
       {
       
          KeyPressDelayTime = 0;//按键按下延时时间变量清0 为了跳出设置按键短按延时 进入设置按键长按延时
    	  AddKeyShortPressLcokFlag = 1;//增加按键短按按下锁定标志位变量置1 跳出增加按键短按 进入增加按键长按 防止增加按键长按时进入短按 从而实现短按与长按互不干扰
    	 }
        }
    	 if(KeyPressDelayTime > KeyLongPressDelayTime)//判断按键按下延时时间变量是否大于按键长按延时时间
       {
       
          KeyPressDelayTime = 0;//按键按下延时时间变量清0 重启下一步按键按下延时操作
    	  AddKeyShortPressLcokFlag = 0;//增加按键短按按下锁定标志位变量置1 防止增加按键长按后松手进入短按 从而实现短按与长按互不干扰 
          AddKeyLongPressLcokFlag = 1;//增加按键长按按下锁定标志位变量置1 一是为了增加按键长按按下后松手再触发其他功能作判断依据 二是为了增加按键长按后松手 防止进入短按 从而实现短按与长按互不干扰
    	  KeyType = 1;//此处是增加按键长按
    	 }
      }
     
    	
       else if((DecKey == 0) && (DecKeyPressLcokFlag == 0))//减少按键按下
     {
       	 
    	AddKeyPressLcokFlag = 1;//增加按键按下锁定标志位变量置1 防止减少按键按下时 有增加按键按下 从而实现增加减少按键互不干扰
    	KeyPressDelayTime++;//按键按下延时时间变量自加
    	if((DecKeyShortPressLcokFlag == 0) && (DecKeyLongPressLcokFlag == 0))//减少按键短按按下锁定标志位变量为0与减少按键长按按下锁定标志位变量为0 一是为了减少按键第1次能短按 二是为了减少按键第1次短按后 如果不松手一直按着 会激活减少按键短按锁定标志位置1 跳出减少按键短按 进入减少按键长按 三是为了减少按键长按后松手 防止进入短按 从而实现短按与长按互不干扰 
      {
       	 
    	 if(KeyPressDelayTime > KeyPressDeshakeTime)//判断按键按下延时时间变量是否大于按键按下消抖时间
       {
       
          KeyPressDelayTime = 0;//按键按下延时时间变量清0 为了跳出设置按键短按延时 进入设置按键长按延时
    	  DecKeyShortPressLcokFlag = 1;//减少按键短按按下锁定标志位变量置1 跳出减少按键短按 进入减少按键长按 防止减少按键长按时进入短按 从而实现短按与长按互不干扰
    	 }
        }
    	 else if(KeyPressDelayTime > KeyLongPressDelayTime)//判断按键按下延时时间变量是否大于按键长按延时时间
       {
       
          KeyPressDelayTime = 0;//按键按下延时时间变量清0 重启下一步按键按下延时操作
    	  DecKeyShortPressLcokFlag = 0;//减少按键短按按下锁定标志位变量置1 防止减少按键长按后松手进入短按 从而实现短按与长按互不干扰 
          DecKeyLongPressLcokFlag = 1;//减少按键长按按下锁定标志位变量置1 一是为了减少按键长按按下后松手再触发其他功能作判断依据 二是为了减少按键长按后松手 防止进入短按 从而实现短按与长按互不干扰
    	  KeyType = 2;//此处是减少按键长按
    	 }
       } 
       //以下表示减少按键弹起或没按下
       else if(DecKeyShortPressLcokFlag == 1)//表示短按过 判断减少按键短按按下锁定标志位变量是否为1 为了减少按键短按按下后松手再触发其他功能 而不受其他抖动影响
     {
       
    	KeyPressDelayTime = 0;//按键按下延时时间变量清0 重启下一步按键按下延时操作
        KeyLiftDelayTime++;//按键弹起延时时间变量自加
    	if(KeyLiftDelayTime > KeyPressDeshakeTime)//判断按键弹起延时时间变量是否大于按键按下消抖时间
      {
        
    	 KeyLiftDelayTime = 0;//按键弹起延时时间变量清0 重启下一步按键弹起延时操作
    	 DecKeyShortPressLcokFlag = 0;//减少按键短按按下锁定标志位变量置0 为了重启下一步减少按键短按按下操作
    	 DecKeyLongPressLcokFlag = 0;//减少按键长按按下锁定标志位变量置0 为了重启下一步减少按键长按按下操作
    	 KeyType = 2;//此处是减少按键短按 对于按键计数或按键类型触发操作 建议要放在按键弹起后再计数 此处就是
         AddKeyPressLcokFlag = 0;//解除增加按键按下锁定标志位	
    	}
       }
       //以下表示减少按键弹起或没按下
       else if(DecKeyLongPressLcokFlag == 1)//表示长按过 判断减少按键长按按下锁定标志位变量是否为1 为了减少按键长按按下后松手再触发其他功能 而不受其他抖动影响
     {
       
        KeyPressDelayTime = 0;//按键按下延时时间变量清0 重启下一步按键按下延时操作
        KeyLiftDelayTime++;//按键弹起延时时间变量自加
        if(KeyLiftDelayTime > KeyPressDeshakeTime
  • 相关阅读:
    LLM - Make Causal Mask 构造因果关系掩码
    MySQL的进阶篇1-MySQL的存储引擎简介
    Python数据分析实验一:Python数据采集与存储
    ​【原创】基于SSM的物流管理系统(物流管理系统毕业设计源代码)
    c++内存对齐
    【自然语言处理】理解词向量、CBOW与Skip-Gram模型
    开发工具记录
    设备互联(一)
    Arbitrum奥德赛第一周跨链桥任务教程
    前端vue实现圣杯布局【flex布局、浮动布局】
  • 原文地址:https://blog.csdn.net/CWQLTYH/article/details/138560369