精华内容
下载资源
问答
  • 51单片机双串口程序

    2014-04-11 14:19:33
    51单片机双串口程序,模拟两路单片机串口通讯。
  • 51单片机串口通讯详解

    千次阅读 多人点赞 2019-11-04 22:10:20
    由于大部分51单片机不支持在线调试功能,所以串口作为一种有效的调试功能,所以在51单片机程序开发时,无法进行在线调试,不妨可以多采用串口来进行调试。 1.串口配置 51单片机配置除了需要配置2个8位寄存器SCON、...

    串口,作为单片机程序开发中最常用、最方便,也是应用最广泛的程序调试方法;无论是作为调试工具,打印出调试信息,还是对功能模块进行通信,串口是每个单片机开发人员最常用的单片机外设。
    由于大部分51单片机不支持在线调试功能,所以串口作为一种有效的调试功能,所以在51单片机程序开发时,无法进行在线调试,不妨可以多采用串口来进行调试。
    1.串口配置

    51单片机配置除了需要配置2个8位寄存器SCON、PCON外,还要配置定时器1的控制寄存器TMOD,因为串口在进行收发需要使用定时器来采样。
    (1)状态控制寄存器 SCON
    SCON 是一个逐位定义的 8 位寄存器,用于控制串行通信的方式选择、接收和发送,指 示串口的状态,SCON 即可以字节寻址也可以位寻址,字节地址 98H,地址位为 98H~9FH。 它的各个位定义如下:
    在这里插入图片描述
    SM0 和 SM1 是串口的工作方式选择位,2 个选择位对应 4 种工作方式,如下表,其中 Fosc 是振荡器的频率。
    在这里插入图片描述
    (2)电源与波特率控制寄存器
    控制寄存器 PCON 也是一个逐位定义的 8 位寄存器,目前仅仅有几位有定义,如下所示:
    在这里插入图片描述
    仅最高位 SMOD 与串口的控制有关,其他位与掉电方式有关。PCON 的地址为 87H 只能按 字节寻址,SMOD 是串行通信波特率系数控制位,当串口工作在工作方式 1、2 时,若使用 T1 作为波特率发生器其 SMOD=1 则波特率加倍。
    (3)定时器控制模式寄存器
    TMOD是定时器、计数器模式控制寄存器,它是一个逐位定义的8为寄存器,但只能使用字节寻址
    在这里插入图片描述
    当串口工作在工作方式0和2是,波特率固定,方式0时fosc/12;方式2时fosc/32或fosc/64(根据SMOD判断)。当串口工作在方式1时,波特率=(2^SMOD/32)*(单片机时钟频率/(256-X)),X是初值;C/T#为定时器和计数器选择位,0为定时器,1为计数器

    2.串口通用程序
    为了有较好的通用性,将串口程序配置为一个H文件和C文件,往后只要开发51单片机程序,都可以将该两个文件复制在工程中直接使用,无须修改。
    (1)uart.H

    #ifndef _UART_H_
    #define _UART_H_
    
    #include "reg52.h"
    
    void UartInit(void);
    void Send_string(unsigned char *c);
    void Send_Data(unsigned char DAT);
    
    #endif
    

    (2)uart.c

    #include "uart.h"
    
    //串口初始化
    void UartInit(void)
    {
    	/*串口初始化 */
    	TMOD = 0x20;	  //定时器T1使用工作方式2
    	SCON = 0x50;	  //工作方式1,,允许接收   
    	PCON = 0x10;
    	TH1 = 253;        // 设置初值,波特率9600bps
    	TL1 = 253;
    	TR1 = 1;          // 开始计时	
    	ES = 1;         //打开接收中断
    	EA = 1;           // 打开所以中断   
    	TI = 0;
    	RI = 0;
    }
    
    void Send_Data(unsigned char DAT)
    {
    	ES = 0;
    	TI=0;
    	SBUF = DAT ;
    	while(TI==0);
    	TI=0;
    	ES = 1;
    }
    
    void Send_string(unsigned char  *c)
    {
    	while(*c != '\0')
    	{
    		Send_Data(*c++);
    	}	
    }
    
    void RSINTR() interrupt 4 using 2
    {
    	EA=0;
    	if(TI==1) //发送中断	  
    	{
    		TI=0;
    	}
    
    	if(RI==1)	 //接收中断		  
    	{	
    
    		RI=0;								 
    
    	}
    	EA=1;
    }
    
    

    如需串口参考例程, 请关注公众号,首页回复“串口”获取资料
    在这里插入图片描述

    展开全文
  • 解决51单片机串口发送汉子显示乱码的问题。
  • 适用于AT89c51/52单片机串口通信例程,可根据实际需求更改发送的数据和发送波特率
  • 51单片机串口通信原理讲解

    千次阅读 多人点赞 2019-10-24 23:54:50
    51单片机串口通信 今天研究了一下51单片机串口通信,使用的单片机是普中科技开发板,但实际上所运用到的硬件和其他品牌单片机都相同,没有区别,总结一下,自己的理解和看法。 通信原理 通信原理大致分为串行和...

    51单片机串口通信


    今天研究了一下51单片机的串口通信,使用的单片机是普中科技开发板,但实际上所运用到的硬件和其他品牌单片机都相同,没有区别,总结一下,自己的理解和看法。

    通信原理

    通信原理大致分为串行和并行两种方法,各有优缺点,也不再这里赘述了,使用到的是串行通信的方法,简单介绍一下串行通信的原理,上图

    两个设备,一根互传线,每次传一组数据,总长度不一定8位,由51单片机内部设定来决定。设备间通信有许多接口方式,我用的是51上的串行接口,挂图:
    在这里插入图片描述
    SBUF:是指串行口中的两个缓冲寄存器,一个是发送寄存器,一个是接收寄存器,在物理结构上是完全独立的,但地址是重叠的。它们都是字节寻址的寄存器,字节地址均为99H,
    TXD:Transmit(tx) Data; RXD: Receive(rx) Data;
    两个口通过缩写记一下,我经常记不住(丢人),所以上面的那一个SBUF是发送,下面的是接收寄存器,发送或者接收的数据将暂时储存于里面,编程时直接赋值就行,TH1和TL1是时钟的配置系统,主要用于控制波特率,及每秒发送的总位数。(调试时一定要对应自己设置的波特率)

    控制寄存器SCON:内部结构下图,主要用于设置串口工作方式、接发送控制,以及状态位的控制
    在这里插入图片描述
    SM0和SM1是控制工作方式下图,控制每组总数据(起止位+数据位)的位数。移位则是一个脉冲一个一个脉冲的发送输入输出数据。
    SM2多机通信控制位,方式2和3时。SM2控制RB8是否会触发RI中断,SM2=1时R8=1激活中断(中断将数据读走),R8=0则不激活;SM2=0则失去控制作用。不论RB是否为0,RI都能激活,方式0时,SM2必须为0;方式1时,SM2=0,接受到停止位,R1中断就打开。
    REN允许串行接受位,REN=1,则打开接受,否则不能接受数据。
    TB,方式2和3中才用到,是奇偶效验位
    RB,在方式2、3中还是做奇偶效验位,在方式1中做数据停止位的存放位,用来将RI自动置1,启动中断。
    在这里插入图片描述
    PCON:用于控制波特率是否加倍,及SMOD=1,波特率加倍。复位时SMOD=0;
    在这里插入图片描述
    好了,大致通信原理讲到这里,下面到使用讲解!

    程序编写

    步骤:
    1、确定TMOD(计数器)工作方式
    2、配置TH1和TL1初值
    3、配置SCON、PCON
    4、打开中断允许位(总中断、串口中断),配置中断(中断内主要是SBUF读取发送数据),配置TCON打开中断即TR1置1.

    上代码:作用串口通信输入值,再返回

    include<reg52.h>
    typedef unsigned char u8;
    
    void ready(void)
    {
    	TMOD = 0X20;
    	TH1=0XFF;
    	TL1=0XF9; //波特率9600
    	SCON=0X50;//0101 0000
    	PCON=OX80;//1000 0000
    	EA=1; //打开总中断
    	ES=1; //打开串口中断,相当于ET1 ET0
    	TR1=1;//打开计数器,当其溢出时会给SMOD一个脉冲,接受和读取数据,达到设置波特率作用
    		  //当接受到停止位时RI=1触发中断
    }
    
    void main(void)
    {
    	ready();
    	while(1);
    }
    
    void time1(void) interrupt 4
    {
    	static u8 result;
    	result=SBUF;//进入配置中断,读取数据
    	RI=0;
    	SBUF=result;//将数据输入到SBUF里面发送
    	while(!TI);//等待发送完毕
    	TI=0;
    }
    

    一个简单的串口通信收发完成了

    展开全文
  • 51 单片机串口通信程序,RS232串口通信 含详细例子。 含详细例子,RS232串口通信单片机接收发送数据的 C51程序,手把手教你用增强型51 实验板实现RS232 串口通信 51串口通信
  • 51单片机串口通信(字符串接收和发送),非常详细,是实际做项目的好帮手
  • 51单片机与上位机串口通讯,通过上位机发送ASCII给51单片机51单片机数码管显示ASCCII值(包括课程设计文档,上位机和51单片机的源码,可直接使用)
  • STC51单片机的高级版本烧录器,包含串口开发助手功能,可选择发送多字节数据
  • 51单片机串口多字节接收
  • STC12C5A60S2单片机双串口通信,互相发送 STC12C5A60S2单片机拥有两个全双工串行通信接口, 串口1的功能及操作与传统51单片机串行相同; 特殊的是STC12C5A60S2单片机内部有一个独立波特率发生器, 串口1可以使用...

    STC12C5A60S2单片机双串口通信,互相发送

    STC12C5A60S2单片机拥有两个全双工串行通信接口,
    串口1的功能及操作与传统51单片机串行相同;
    特殊的是STC12C5A60S2单片机内部有一个独立波特率发生器,
    串口1可以使用定时器1作为波特率发生器,也可以使用独立波特率发生器作为波特率发生器;
    而串口2只能使用独立波特率发生器作为波特率发生器。

    /*-----------------------------------------------
    名称:STC12C5A60S2双串口通信,单片机后缀s2意思就是双串口
    内容:9600波特率 双串口收发
    接线:串口1 发送P3.1,接收P3.0
         串口2 发送P1.3,接收P1.2
         串口2具体引脚是可修改的。
      STC12CSA60S2系列单片机串行口1对应的硬件部分是TxD/P3.1和RxD/P3.0引脚,串行口2对应的硬件部分是TxD2和RxD2。通过设置特殊功能寄存AUXR1中的S2_P4/AUXR1.4位,串行口2(UART2)功能可以在P1口和P4口之间任意切换。当串行口2功能在P1口实现时,对应的管脚是P1.2/RxD2和P1.3/IxD2。当串行口2功能在P4口实现时,对应的管脚是P4.2/RxD2和P4.3/TxD2。
    ------------------------------------------------*/
    
    #include"stc12c5a60s2.h"
    #include"delay.h"
    
    #define S2RI 0x01   //串口2接收中断中断请求标志位
    #define S2TI 0x02   //串口2发送中断请求标志位
    unsigned char flag1,flag2,temp1,temp2;
    unsigned char uart2Receive[100];
    unsigned char uart1Receive[100];
    unsigned int point1=0,point2=0;
    unsigned char i;
    /*------------------------------------------------
                       函数声明
    ------------------------------------------------*/
    //void SendStr(unsigned char *s);
    void UART_1SendOneByte(unsigned char c);
    void UART_2SendOneByte(unsigned char c);
    void uart1SendStr(unsigned char *s);
    void uart2SendStr(unsigned char *s);
    /*------------------------------------------------
                        串口初始化
    ------------------------------------------------*/
    void InitUART  (void)
    {
    
        SCON  = 0x50;       // SCON: 模式 1, 8-bit UART, 使能接收  
        TMOD |= 0x20;       // TMOD: timer 1, mode 2, 8-bit 重装
        TH1   = 0xFD;       // TH1:  重装值 9600 波特率 
                            // 晶振 11.0592MHz  
        TR1   = 1;          // TR1:  timer 1 打开                    
        EA    = 1;           //打开总中断
        ES    = 1;         //打开串口中断
          
        S2CON = 0x50; //串口2工作在方式1  10位异步收发
                      // S2REN=1允许接收
        BRT = 0xFD;    //  9600 
        AUXR = 0x10;  //BRTR=1 独立波特率发生器开始计数
        IE2 =0x01;   //开串口2中断  ES2=1
    }                           
    /*------------------------------------------------
                        主函数
    ------------------------------------------------*/
    void main (void)
    {
    
      InitUART();
      DelayMs(100);
      uart1SendStr("串口1初始化成功");
      DelayMs(100);
      uart2SendStr("串口2初始化成功");
      while (1)                       
        {
           if(flag1==1)  
            {  
                flag1=0;             
            // uart2SendStr("串口1中断,串口2发送串口1接收的数据:");                               
                uart1SendStr(uart1Receive);
              for(i=0;i<=100;i++)
             {
                 uart1Receive[i]=0;
             }
           }  
    	     if(flag2==1)  
    	     {  
    	       flag2=0;   
    	     //  uart1SendStr("串口2中断,串口1发送串口2接收的数据:");
    	       uart2SendStr(uart2Receive);  
    	       for(i=0;i<=100;i++)
    	       {  
    	            uart2Receive[i]=0;                                                           
    	       }
    	     }  
        }
    }
    
    /*------------------------------------------------
                        1发送字符串
    ------------------------------------------------*/
    void uart1SendStr(unsigned char *s)
    {
    while(*s!='\0')// \0 表示字符串结束标志,
                    //通过检测是否字符串末尾
      {
      UART_1SendOneByte(*s);
      s++;
      }
    }
    /*------------------------------------------------
                        2发送字符串
    ------------------------------------------------*/
    
    void uart2SendStr(unsigned char *s)
    {
        while(*s!='\0')    // \0 表示字符串结束标志,
                       //通过检测是否字符串末尾
        {
    	  UART_2SendOneByte(*s);
    	  s++;
        }
    }
    
    void UART_1SendOneByte(unsigned char c)  
    {  
        SBUF = c;  
        while(!TI);    //?TI=0,????  
        TI = 0;   
    }
    
    
    /****************串口2发送一个字符****************/  
    void UART_2SendOneByte(unsigned char c)  
    {  
        S2BUF = c;  
        while(!(S2CON&S2TI));  //?S2TI=0,????  
        S2CON&=~S2TI;     //S2TI=0  
    }  
    /************串口1中断函数*************/  
    void UART_1Interrupt(void) interrupt 4  
    {  
        if(RI==1)  
        {  
            RI=0;  
            flag1=1;  
            temp1=SBUF;
                                    uart1Receive[point1++]=temp1;
                            if(temp1=='\n')
                            {
                                    flag1=1;
                                    point1=0;
                            }
                            if(point1==100)
                            {
                                    point1=0;
          }
        }  
    }  
    /************串口2中断函数*************/  
    void UART_2Interrupt(void) interrupt 8  
    {  
             EA    = 0;                  //打开总中断
        if(S2CON&S2RI)  
        {  
            S2CON&=~S2RI;         
            temp2=S2BUF;
            uart2Receive[point2++]=temp2;
            if(temp2=='\n')
            {
                    point2=0;
                    flag2=1;
            }
            if(point2==100)
            {
                    point2=0;
          }
        }
    EA    = 1;                  //打开总中断               
    }
    
    
    展开全文
  • 51单片机串口驱动,个人正在使用中,比较好用。
  • 51单片机——串口通信

    千次阅读 2021-06-17 23:28:18
    51单片机——串口通信串口通信?串口通信的原理?串口的配置定时器的配置c源代码netty源代码结果 本篇博客的最终效果是实现51单片机串口发送Hello World,netty监听串口读到Hello World后回发给51单片机,最终51...


    本篇博客的最终效果是实现51单片机用串口发送Hello World,netty监听串口读到Hello World后回发给51单片机,最终51单片机回显到LCD1602显示屏。

    串口通信?

    其实我压根不知道串口通信是啥,我在这方面也是小白,只知道按照标准做就可以实现通信。
    在这里插入图片描述
    上图示是四孔串口,应该算是全双工通信的,复杂的有9针串口,提供额外的口子可以调控发送速率等。

    在这里插入图片描述

    开发板原理图如下:
    在这里插入图片描述

    串口通信的原理?

    我们知道串口通信是要设置一个波特率的,比如4800bit/s, 那么这个数据发送速率如何控制呢?
    定时器那篇博客里说了12MHz的晶振,一个指令周期是1us,每过一个1us,定时器+1,加到溢出了,发出一个溢出中断,然后就去发送码元数据,这样去控制码元的发送速率。

    定时器初值的计算
    关于串口定时器初值计算,我没搞懂,但是他有公式,套用公式即可
    公式:TL1 = 256 - fosc * (SMOD + 1) / (384 * 波特率)
    我的单片机是11.0592MHz,fosc=11.0592*1000000, 晶振每s振动次数
    TL1= 256 - 11059200/384/4800 = 250 = 0xFA

    这里用的定时器是定时器1,8位重装,8位最大255,加到溢出值256,初始值和重装值都设置为0xFA
    TL1 = 0xFA; //设定定时初值
    TH1 = 0xFA; //设定定时器重装值

    软件计算
    感觉之所以出11.0592MHz的原因可能就是用这个计算误差为0,如果是12MHz的不管怎么计算都会有误差,但是12MHz的采用12分频的话一个指令周期正好1us。
    在这里插入图片描述

    串口的配置

    在这里插入图片描述SCON配置
    在这里插入图片描述REN::接收使能,为0代表51单片机的串口不接受数据,我们需要接收置位为1
    TB8,RB8:不用管,只有在方式2和方式3 9位UART下才用得到
    TI:发送数据中断标志位,在发完8位数据后,由内部硬件自动置位为1,我们需要软件复位为0
    RI:接收数据中断标志位,在接完8位数据后,由内部硬件自动置位为1,我们需要软件复位为0
    SCON=0x50

    SBUF是一字节缓冲区,发送的时候直接SBUF='A’就把A发送到串口了,接收的时候char a = SBUF就可以了

    PCON配置
    在这里插入图片描述
    B7的SMOD=1开启倍速,我们不需要倍速,8为全0就好。
    PCON=0; 为了不影响其他位一般这样写PCON &= 0x7F;

    IE配置
    这里配的是UART中断的配置‘
    在这里插入图片描述EA=1,ES=1允许UART中断,netty从串口发来的数据,是要经过这个中断处理程序的:void UART_Routine() interrupt 4

    串口模式图:
    在这里插入图片描述
    在这里插入图片描述

    定时器的配置

    之前有详细说过定时器0的配置,这里就不说了,具体查看STC89C52文档第7章

    	//定时器配置
    	TMOD &= 0x0F;		//清除定时器1模式位
    	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
    	//上面两行等价TMOD=0x20
    	TL1 = 0xFA;		//设定定时初值
    	TH1 = 0xFA;		//设定定时器重装值
    	ET1 = 0;		//禁止定时器1中断,这里不需要定时器的中断,只需要计时
    	TR1 = 1;		//启动定时器1
    

    c源代码

    Delay.c

    
    void Delay(unsigned int xms)
    {
    	unsigned char i, j;
    	while(xms--)
    	{
    		i = 2;
    		j = 239;
    		do
    		{
    			while (--j);
    		} while (--i);
    	}
    }
    
    
    

    Delay.h

    #ifndef __DELAY_H__
    #define __DELAY_H__
    
    void Delay(unsigned int xms);
    
    #endif
    
    

    LCD1602.c

    #include <REGX52.H>
    #include <Delay.h>
    //引脚配置:
    sbit LCD_RS=P2^6;
    sbit LCD_RW=P2^5;
    sbit LCD_EN=P2^7;
    #define LCD_DataPort P0
    
    
    /**
      * @brief  LCD1602写命令
      * @param  Command 要写入的命令
      * @retval 无
      */
    void LCD_WriteCommand(unsigned char Command)
    {
    	LCD_RS=0;
    	LCD_RW=0;
    	LCD_DataPort=Command;
    	LCD_EN=1;
    	Delay(1);
    	LCD_EN=0;
    	Delay(1);
    }
    
    /**
      * @brief  LCD1602写数据
      * @param  Data 要写入的数据
      * @retval 无
      */
    void LCD_WriteData(unsigned char Data)
    {
    	LCD_RS=1;
    	LCD_RW=0;
    	LCD_DataPort=Data;
    	LCD_EN=1;
    	Delay(1);
    	LCD_EN=0;
    	Delay(1);
    }
    
    /**
      * @brief  LCD1602设置光标位置
      * @param  Line 行位置,范围:1~2
      * @param  Column 列位置,范围:1~16
      * @retval 无
      */
    void LCD_SetCursor(unsigned char Line,unsigned char Column)
    {
    	if(Line==1)
    	{
    		LCD_WriteCommand(0x80|(Column-1));
    	}
    	else if(Line==2)
    	{
    		LCD_WriteCommand(0x80|(Column-1+0x40));
    	}
    }
    
    /**
      * @brief  LCD1602初始化函数
      * @param  无
      * @retval 无
      */
    void LCD_Init()
    {
    	LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
    	LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
    	LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
    	LCD_WriteCommand(0x01);//光标复位,清屏
    }
    
    /**
      * @brief  在LCD1602指定位置上显示一个字符
      * @param  Line 行位置,范围:1~2
      * @param  Column 列位置,范围:1~16
      * @param  Char 要显示的字符
      * @retval 无
      */
    void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
    {
    	LCD_SetCursor(Line,Column);
    	LCD_WriteData(Char);
    }
    
    /**
      * @brief  在LCD1602指定位置开始显示所给字符串
      * @param  Line 起始行位置,范围:1~2
      * @param  Column 起始列位置,范围:1~16
      * @param  String 要显示的字符串
      * @retval 无
      */
    void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
    {
    	unsigned char i;
    	LCD_SetCursor(Line,Column);
    	for(i=0;String[i]!='\0';i++)
    	{
    		LCD_WriteData(String[i]);
    	}
    }
    
    /**
      * @brief  返回值=X的Y次方
      */
    int LCD_Pow(int X,int Y)
    {
    	unsigned char i;
    	int Result=1;
    	for(i=0;i<Y;i++)
    	{
    		Result*=X;
    	}
    	return Result;
    }
    
    /**
      * @brief  在LCD1602指定位置开始显示所给数字
      * @param  Line 起始行位置,范围:1~2
      * @param  Column 起始列位置,范围:1~16
      * @param  Number 要显示的数字,范围:0~65535
      * @param  Length 要显示数字的长度,范围:1~5
      * @retval 无
      */
    void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
    {
    	unsigned char i;
    	LCD_SetCursor(Line,Column);
    	for(i=Length;i>0;i--)
    	{
    		LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
    	}
    }
    
    /**
      * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
      * @param  Line 起始行位置,范围:1~2
      * @param  Column 起始列位置,范围:1~16
      * @param  Number 要显示的数字,范围:-32768~32767
      * @param  Length 要显示数字的长度,范围:1~5
      * @retval 无
      */
    void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
    {
    	unsigned char i;
    	unsigned int Number1;
    	LCD_SetCursor(Line,Column);
    	if(Number>=0)
    	{
    		LCD_WriteData('+');
    		Number1=Number;
    	}
    	else
    	{
    		LCD_WriteData('-');
    		Number1=-Number;
    	}
    	for(i=Length;i>0;i--)
    	{
    		LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
    	}
    }
    
    /**
      * @brief  在LCD1602指定位置开始以十六进制显示所给数字
      * @param  Line 起始行位置,范围:1~2
      * @param  Column 起始列位置,范围:1~16
      * @param  Number 要显示的数字,范围:0~0xFFFF
      * @param  Length 要显示数字的长度,范围:1~4
      * @retval 无
      */
    void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
    {
    	unsigned char i,SingleNumber;
    	LCD_SetCursor(Line,Column);
    	for(i=Length;i>0;i--)
    	{
    		SingleNumber=Number/LCD_Pow(16,i-1)%16;
    		if(SingleNumber<10)
    		{
    			LCD_WriteData(SingleNumber+'0');
    		}
    		else
    		{
    			LCD_WriteData(SingleNumber-10+'A');
    		}
    	}
    }
    
    /**
      * @brief  在LCD1602指定位置开始以二进制显示所给数字
      * @param  Line 起始行位置,范围:1~2
      * @param  Column 起始列位置,范围:1~16
      * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
      * @param  Length 要显示数字的长度,范围:1~16
      * @retval 无
      */
    void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
    {
    	unsigned char i;
    	LCD_SetCursor(Line,Column);
    	for(i=Length;i>0;i--)
    	{
    		LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
    	}
    }
    
    

    LCD1602.h

    #ifndef __LCD1602_H__
    #define __LCD1602_H__
    
    //用户调用函数:
    void LCD_Init();
    void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
    void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
    void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
    void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
    void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
    void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
    
    #endif
    
    

    UART.h

    #ifndef __UART_H__
    #define __UART_H__
    
    void UART_Init();
    void UART_SendByte(unsigned char Byte);
    
    #endif
    
    

    UART.c

    #include <REGX52.H>
    
    
    //11.0592MHz
    //fosc=11.0592*1000000, 晶振每s振动次数
    // TL1 = 256 - fosc * (SMOD + 1) / (384 * 波特率)
    // TL1= 256 - 11059200/384/4800 = 250 = 0xfa
    void UART_Init()
    {
    	//PCON |= 0x80; //波特率倍速 smod=1,9600
    	//TL1 = 0xF4;		//设定定时初值
    	//TH1 = 0xF4;		//设定定时器重装值
    	PCON=0;
    	//PCON &= 0x7F;		//波特率不倍速 smod=0,4800
    	SCON = 0x50;		//8位数据,可变波特率
    	
    	//定时器配置
    	TMOD &= 0x0F;		//清除定时器1模式位
    	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
    	TL1 = 0xFA;		//设定定时初值
    	TH1 = 0xFA;		//设定定时器重装值
    	ET1 = 0;		//禁止定时器1中断
    	TR1 = 1;		//启动定时器1
    	
    	//串口中断配置
    	EA=1;
    	ES=1;
    }
    /**
      * @brief  串口发送一个字节数据
      * @param  Byte 要发送的一个字节数据
      * @retval 无
      */
    void UART_SendByte(unsigned char Byte)
    {
    	SBUF=Byte;
    	while(TI==0);
    	//到这里说明TI=1,因为硬件置为1
    	//手工复位
    	TI=0;
    }
    
    

    main.c

    #include <REGX52.H>
    #include "Delay.h"
    #include "UART.h"
    #include "LCD1602.h"
    void main()
    {
    	unsigned char cs[] = {0x10,11,'H','e','l','l','o',' ','W','o','r','l','d',0x16};
    	char i = 0;
    	LCD_Init();
    	
    	UART_Init();			//串口初始化
    	
    	Delay(3000);		//延时
    	
    	
    	while(i<14){
    		UART_SendByte(cs[i]);	//串口发送一个字节
    		Delay(10);		//延时
    		i++;
    	}
    			
    	while(1){}
    	
    }
    
    //下面这个中断程序是接收netty的返回数据
    char col = 0;
    unsigned char rcs[14];
    char i = 0;
    void UART_Routine() interrupt 4
    {
    	if(RI==1)					//如果接收标志位为1,接收到了数据
    	{
    		rcs[col++] = SBUF;
    		if(col==14){
    			LCD_ShowString(1,0,rcs);
    		}
    		RI=0;					//接收标志位清0
    	}
    }
    

    netty源代码

    netty代码有点多,我就说个大概,可以去git拉。

    整体流程如下:
    在这里插入图片描述
    协议如下图
    在这里插入图片描述单片机发送的数据如下:
    unsigned char cs[] = {0x10,11,‘H’,‘e’,‘l’,‘l’,‘o’,’ ',‘W’,‘o’,‘r’,‘l’,‘d’,0x16};

    第一步经过FrameDecoder
    在这里插入图片描述
    第二步经过PacketDecoder
    在这里插入图片描述第三步经过PacketHandler
    在这里插入图片描述

    git码云代码,代码在com.lry.netty01.rx,其他代码不用管,另外java串口通信需要一些jar包,放到jdk里面,具体的自己搜搜看

    结果

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

    展开全文
  • stc51单片机串口通信程序

    万次阅读 多人点赞 2019-04-12 17:37:06
    51单片机串口通信,是全双工的,就是可以同时收/发的,互相不影响的。 串口是可以同时收/发的,虽然都是用SBUF,但却是两个独立的寄存器,互不影响,只是都叫一个名,SBUF。 但是,对于接收或发送,确实是接收到一...
  • MPU6050 51单片机读取并通过串口输出,KEIL4开发环境。6050角度传感器,51单片机开发六轴传感器
  • 51单片机串口通信(一)

    万次阅读 多人点赞 2018-12-02 18:27:07
    串口通信好东西,但我没用过。 下面照着普中科技的ppt搬运下。  随着多微机系统的广泛应用和计算机网络技术的普及,计算机的通信功能愈来愈显得重要。计算机通信是指计算机与外部设备或计算机与计算机之间的信息...
  • 一个一看就懂得51单片机RS232串口程序
  • 51单片机串口通信详解

    千次阅读 多人点赞 2020-10-05 19:36:02
    51单片机自身有圈双工的异步通信串口。 2、串口通信的通信方式 串口通信基本通信方式有两种:并行通信和串行通信。 串行通信:传送数据的各位按顺序一位一位发送或者接收 并行通信:传送数据各位同时发送或接收 3、...
  • 51单片机串口程序,字符串16进制发送与接收.docx
  • 描述STC51单片机一般带有1个串口,有的带有2个串口串口一般用于下载程序和串口通信。串口通信特别适合控制设备,所以工控机的电脑上一般都带有串口51单片机串口引脚为P3.0引脚与P3.1引脚,分别是RXD和TXD引脚...
  • 51单片机串口通信(字符串接收和发送)
  • 无线串口模块与51单片机通信测试程序,实现无线串口通讯,模块接口为通用的TTL串口
  • 51单片机~串口通信(讲解+代码)

    千次阅读 多人点赞 2021-04-22 16:36:39
    51单片机~串口通信 (一)计算机串行通信原理:
  • 51单片机——串口1收发

    千次阅读 2021-03-16 10:50:24
    修改串口初始化,不加这几个没法接收 TI=0; RI=0; REN=1; //不开启这个无法接受数据 //PS=1; //提高串口中断优先级 ES=1; //开启串口中断使能 EA=1; 2.问题 修改后发现有不合理的地方,待后期修改,如下图...
  • 本文为笔者学习过程的笔记,主要内容为串口通信,使用的开发板为51单片机,后期会补充其他平台。 提示:以下是本篇文章正文内容,下面案例可供参考 一、计算机通信简介 概念:计算机与外部设备或计算.
  • 51单片机的基础程序之一,串口通讯,有兴趣的可以下载玩一下,里面包含了串口通信工具,方便快捷
  • 实验是两个80C51单片机利用proteus进行串口通信仿真,包括软件的源代码。可以作为测试评估使用。
  • 51单片机串口应用实例(汇编)

    千次阅读 2020-11-18 23:26:42
    猜数字小游戏:串行口发送0x01、0x02、0x03 HEX数据中的一个到51单片机,对应的按键key1-key3,发送数据之后,另一边人员猜测对应的HEX码,并按下对应的按键,若按下正确的按键,则LED灯闪烁,按下不正确的按键,则...
  • STC12C60S2单片机双串口程序,经本人在Keil UV3中测试,下载后没有问题。
  • ESP8266wifi模块与51单片机通信教程

    万次阅读 多人点赞 2019-11-10 17:45:59
    ESP8266wifi模块与51单片机通信教程 准备两个200欧左右的电阻 准备6根杜邦线 然后将ES8266通过如图这种方式连接起来 注意:在连接单片机的RX和TX引脚时必须和ESP8266模块的RX和TX反接才能保证正常通信 将程序下载...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 18,436
精华内容 7,374
关键字:

双串口51单片机