51单片机 串口_51单片机串口 - CSDN
精华内容
参与话题
  • 51单片机串口驱动,个人正在使用中,比较好用。
  • 51单片机串口通信(一)

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

    串口通信好东西,但我没用过。

    下面照着普中科技的ppt搬运下。


           随着多微机系统的广泛应用和计算机网络技术的普及,计算机的通信功能愈来愈显得重要。计算机通信是指计算机与外部设备或计算机与计算机之间的信息交换。

    通信方式

    并行通信串行通信两种。

    并行通信通常是将数据字节的各位用多条数据线同时进行传送 。

    图一:并行通信

    串行通信是将数据字节分成一位一位的形式在。

    图二:串行同行

     

     

     

     

     

    串行通信的传输方向

    单工是指数据传输仅能沿一个方向,不能实现反向传输。

    半双工是指数据传输可以沿两个方向,但需要分时进行。

    全双工是指数据可以同时进行双向传输。

     

    串行通信常见的错误校验 

    奇偶校验、循环冗余校验

     

    传输速率(比特率):

    比特率是每秒钟传输二进制代码的位数,单位是:位/秒(bps)。

     

    80C51串行口的结构

    图三:串口结构

     有两个物理上独立的接收、发送缓冲器SBUF,它们占用同一地址99H ;接收器是双缓冲结构 ;发送缓冲器,因为发送时CPU是主动的,不会产生重叠错误。

     

    串行口的控制寄存器(SCON)(有点复杂,没咋整明白,以后用的时候再说)

    用以设定串行口的工作方式、接收/发送控制以及设置状态标志:

    图四:SCON

    SM0和SM1为工作方式选择位,可选择四种工作方式:

    图五:工作方式

    SM2,多机通信控制位,主要用于方式2和方式3。当接收机的SM2=1时可以利用收到的RB8来控制是否激活RI(RB8=0时不激活RI,收到的信息丢弃;RB8=1时收到的数据进入SBUF,并激活RI,进而在中断服务中将数据从SBUF读走)。当SM2=0时,不论收到的RB8为0和1,均可以使收到的数据进入SBUF,并激活RI(即此时RB8不具有控制RI激活的功能)。通过控制SM2,可以实现多机通信。在方式0时,SM2必须是0。在方式1时,如果SM2=1,则只有接收到有效停止位时,RI才置1。

    REN,允许串行接收位。由软件置REN=1,则启动串行口接收数据;若软件置REN=0,则禁止接收。

    TB8,在方式2或方式3中,是发送数据的第九位,可以用软件规定其作用。可以用作数据的奇偶校验位,或在多机通信中,作为地址帧/数据帧的标志位。在方式0和方式1中,该位未用。

    RB8,在方式2或方式3中,是接收到数据的第九位,作为奇偶校验位或地址帧/数据帧的标志位。在方式1时,若SM2=0,则RB8是接收到的停止位。

    TI,发送中断标志位。在方式0时,当串行发送第8位数据结束时,或在其它方式,串行发送停止位的开始时,由内部硬件使TI置1,向CPU发中断申请。在中断服务程序中,必须用软件将其清0,取消此中断申请

    RI,接收中断标志位。在方式0时,当串行接收第8位数据结束时,或在其它方式,串行接收停止位的中间时,由内部硬件使RI置1,向CPU发中断申请。也必须在中断服务程序中,用软件将其清0,取消此中断申请。 

    PCON中只有一位SMOD与串行口工作有关

    图六:PCON

    SMOD(PCON.7)  波特率倍增位。在串行口方式1、方式2、方式3时,波特率与SMOD有关,当SMOD=1时,波特率提高一倍。复位时,SMOD=0。 

     

    波特率的计算(用波特率计算器)

    方式0的波特率 =  fosc/12

    方式2的波特率 =(2SMOD/64)· fosc

    方式1的波特率 =(2SMOD/32)·(T1溢出率)

    方式3的波特率 =(2SMOD/32)·(T1溢出率)

     T1 溢出率 = fosc /{12×[256 -(TH1)]}

           在单片机的应用中,常用的晶振频率为:12MHz和11.0592MHz。所以,选用的波特率也相对固定。常用的串行口波特率以及各参数的关系如表所示。

    图七:波特率

    串口如何使用 

    确定串行口控制(编程SCON寄存器);

    确定T1的工作方式(编程TMOD寄存器);

    计算T1的初值,装载TH1、TL1;

    启动T1(编程TCON中的TR1位);

    PC和单片机通信:

    #include<reg52.h>
    
    typedef unsigned char uchar;
    
    void Serial_comInit()
    {
    	SCON=0X50;			//设置为工作方式1 ,既然是方式一,自然要确定波特率,设置定时器1
    	TMOD=0X20;//8位重装载
    	PCON=0X80;
    	TH1=0xF3;//波特率4800
    	TL1=0XF3;
    	ES=1;						//打开通信中断
    	EA=1;						//打开总中断
    	TR1=1;					//打开计数器
    }
    
    void main(void)
    {
    	Serial_comInit();
    	while(1);
    }
    
    void communication() interrupt 4
    {
    	uchar receiveData;
    	receiveData=SBUF;//出去,接,收到的数据
    	RI = 0;//清除接收中断标志位
    	SBUF=receiveData;//将接收到的数据放入到发送寄存器
    	while(!TI);			 //等待发送数据完成
    	TI=0;						 //清除发送完成标志位
    }

     

     电脑发送数据到单片机:

    (来源:https://blog.csdn.net/u014453898/article/details/57123007

    
    #include<reg52.h>
    
    #define uchar unsigned char
    
    #define uint  unsigned int
    uchar buf;
    
    #define led P2
    
    void main(void)
    
    {
    
    SCON=0x50;//设定串口工作方式0101 0000
    
    PCON=0x00;
    
    TMOD=0x20;
    
    EA=1;
    
    ES=1;
    
    TL1=0xfd;//波特率9600
    
    TH1=0xfd;
    
    TR1=1;
    
    while(1);
    
    }
    
     
    
    //串行中断服务函数
    
    void serial() interrupt 4
    
    	{
    
    	ES=0;		//暂时关闭串口中断
    
    	RI=0;
    
    	buf=SBUF;	//把收到的信息从SBUF放到buf中。
    
    	switch(buf)
    
    	{
    
    	case 0x31: led=0xfe;break;   //二进制 0011 0001  十进制 49 控制字符 1  16进制 0X31
    
    	case 0x32: led=0xfd;break;	 //1111 1101
    
    	case 0x33: led=0xfb;break;
    
    	case 0x34: led=0xf7;break;
    
    	case 0x35: led=0xef;break;   
    
    	case 0x36: led=0xdf;break;	
    
    	case 0x37: led=0xbf;break;
    
    	case 0x38: led=0x7f;break;
    
    	}
    
    	ES=1;		//重新开启串口中断
    
    	SBUF=buf;
    	while(!TI);
    	TI=0;
    
    }
    
     
    

     我的串口助手有点智障,不过程序应该没有啥大问题。

     

    参考文章:

    C51学习五)单片机与PC通过串口通信 

     

       

     

     

     

     

    一条传输线上逐个地传送。

     

     

     

     

    展开全文
  • 51单片机串口通信

    万次阅读 多人点赞 2018-05-15 15:59:13
    好记性不如烂笔头,以前总以为自己记性比较好,但事实总是一次一次的打我脸,刚开始学习单片机的时候在串口通信这一块发了一段时间,才将这一块弄懂了个七七八八,这几天回头想一下那一方面的知识,感觉忘得差不多了...

        好记性不如烂笔头,以前总以为自己记性比较好,但事实总是一次一次的打我脸,刚开始学习单片机的时候在串口通信这一块发了一段时间,才将这一块弄懂了个七七八八,这几天回头想一下那一方面的知识,感觉忘得差不多了,现在重新理一遍,里面的程序大部分都是以前抄袭大佬的,但具体是哪一位大佬的博客现在也找不到了,希望大佬见谅。

        首先了解串口通信先要熟悉SCON,PCON,TMOD三个寄存器

        串口工作方式寄存器SCON,

    D7D6D5D4D3D2D1D0
    功能SM0SM1SM2RENTB8RB8TIRI

    RI:接收中断标志位,数据接收结束时,标志位会自动置1,需要通过程序将其置0

    TI:发送中断标志位,数据发送结束时,标志位会自动置1,需要通过程序将其置0

    RB8:存放发送数据的第9位

    TB8:存放接收数据的第9位

    REN:串行接收允许位,0允许串行接收,1禁止串行接收

    SM2:多机控制位

    SM1,SM0:串行工作方式

    SM0SM1方式说明波特率
    000移位寄存器fosc/12
    01110位异步收发器(8位数据)可变
    10211位异步收发器(9位数据)fosc/64或fosc/32
    11311位异步收发器(9位数据)可变

        PCON寄存器

    D7D6D5D4D3D2D1D0
    功能SMOD-------

    SOMD:波特率是否加倍选择位,0波特率不加倍,1波特率加倍

        定时器工作方式寄存器TMOD

    D7D6D5D4D3D2D1D0
    功能GATEC/TM1M0GATEC/TM1M0

    高四位为定时计数器1的设置,低四位是定时计数器0设置,串口通信波特率设置占用定时计数器1,这里主要说串口通信,不过多说定时计数器,只需要设置定时计数器1的工作方式即可

    振荡周期:也称时钟周期(频率的倒数),单片机提供时钟信号的振荡源周期,频率一般有11.0592MHz,12MHz等

    状态周期:是时钟周期的2倍,

    机器周期:是包含6个状态周期,机器周期=1/单片机时钟频率

    单片机时钟频率:是外部时钟的12分频,如果是12MHz的晶振,机器周期=1/单片机时钟频率=1/(12MHz/12)=12/12M=1us

    这里一个机器周期为1us,若定时时间为1ms,则需要1000个机器周期,计算出初值;如果机器周期为2us,则只需要500个机器周期。

    定时器初值计算:初值=(65536-机器周期数量)


    波特率计算:

    当串口工作在工作方式0和2是,波特率固定,方式0时fosc/12;方式2时fosc/32或fosc/64(根据SMOD判断)。

    当串口工作在方式1时,波特率=(2^SMOD/32)*(单片机时钟频率/(256-X)),X是初值

    C/T:定时器和计数器选择位,0为定时器,1为计数器

    M1M0工作方式
    00

    工作方式0:为13位定时/计数器

    01工作方式1:为16位定时/计数器
    10工作方式2:8位初值自动重装定时/计数器
    11工作方式3:仅适用于T0,分成两个8位计数器,T1停止计数

    下面是程序结构和代码:


    mian.c

    #include "main.h"
    uchar UartRxBuffer[ 64 ] = { 0 };			//uart串口接收数据
    uchar	TX_Cnt = 0;		//发送计数
    uchar	RX_Cnt = 0;		//接收计数
    bit TX_Busy = 0;	  //发送忙标志
    void main()
    {
    	uart_init();
    	while(1)
    	{
    		if((TX_Cnt!=RX_Cnt)&&(!TX_Busy))
    		{
    			//将数组中的数据放入到发送缓冲区
    			SBUF=UartRxBuffer[TX_Cnt];			
    			if(++TX_Cnt>=64)
    			{
    				TX_Cnt=0;
    			}
    			TX_Busy==1;
    		}	
    	}
    }
    
    /*************************************************
    函数:串口程序
    功能:将接收到的数据存入到UartRxBuffer
    *************************************************/
    void UART_INT (void) interrupt 4
    {
    	if(RI)
    	{
    		RI = 0;
    		UartRxBuffer[RX_Cnt] = SBUF;//将数据写入数组
    		//防止溢出,当计数=16时,将计数清零
    		if(++RX_Cnt >= 64){
    			RX_Cnt = 0;
    		}
    	}
    	if(TI)
    	{
    		TI = 0;
    		TX_Busy = 0;
    	}
    }

    mcu_uart.c

    #include "mcu_uart.h"
    
    /*************************************************
    函数:uart_init
    功能:初始化串口
    出口:void
    入口:void
    *************************************************/
    void uart_init()
    {
        SCON = 0x50;//设置串口工作方式1
        TMOD = 0x20;//设置计数器工作方式2
        PCON = 0x00;//即SMOD=1,波特率不加倍
        TH1 = 0xFD;//计数器初值,波特率是9600,晶振为11.0592MHz
        TL1 = 0xFD;
        ES = 1;//打开接收中断
        EA = 1;//打开总中断
        TR1 = 1;//打开计数器		
    }
    
    /*************************************************
    函数:uart_tx_byte
    功能:串口发送一个字节
    出口:void
    入口:一个字节
    *************************************************/
    void uart_tx_byte(uchar str)
    {
    	SBUF=str;
    	while(!TI);
    	TI==0;
    }
    /*************************************************
    函数:uart_tx_string
    功能:串口发送一个字符串
    出口:void
    入口:字符串数组
    *************************************************/
    void uart_tx_string(uchar *str)
    {
    	while(*str!='\0')
    	{
    		uart_tx_byte(*str++);
    	}
    }
    
    /*************************************************
    函数:uart_rx_string
    功能:串口接收一个字符串
    出口:字符串的长度
    入口:字符串数组
    *************************************************/
    uchar uart_rx_string( uchar* RxBuffer )
    {
    	uchar rxLength = 0;
    	uint uartRxTimOut = 0x7FFF;	
    	while( uartRxTimOut-- )
    	{
    		if( 0 != RI )
    		{
    			RI = 0;	
    			*RxBuffer = SBUF;
    			RxBuffer++;
    			rxLength++;
    			uartRxTimOut = 0x7FFF;
    		}
    	}	
    	return rxLength;
    }

    mian.h

    #ifndef __MAIN_H__
    #define __MAIN_H__
    
    #include "mcu_uart.h"
    
    #endif

    mcu_uart.h

    #ifndef __MCU_UART_H__
    #define __MCU_UART_H__
    
    #include "mcu_type.h"
    
    void uart_init();
    #endif

    mcu_type.h

    #ifndef __MCU_TYPE_H__
    #define __MCU_TYPE_H__
    
    #include <reg52.h>
    /*无符号*/
    typedef unsigned char 			uchar;
    typedef unsigned int 				uint;
    
    #endif

    展开全文
  • 基于51 单片机串口收发数据

    万次阅读 热门讨论 2018-10-23 20:43:00
    大多数51单片机用的都是11m晶振而只有少部分用的是奇葩的12m(楼主的就是),在12m晶振进行串口通信时切忌要将波特率设置为4800以下,应为12m晶振的波特率在9600以上误差很大容易丢失数据,动手能力强的可以折腾一下用...

    在进行串口的收发数据过程中一定要注意波特率的问题。

    大多数51单片机用的都是11m晶振而只有少部分用的是奇葩的12m(楼主的就是),在12m晶振进行串口通信时切忌要将波特率设置为4800以下,应为12m晶振的波特率在9600以上误差很大容易丢失数据,动手能力强的可以折腾一下用定时器输出9600波特率。

    至于,串口中断以及波特率的设置可以参考网上例子忒多。

    在用串口助手进行串口收发数据时都会触发串口中断并且在发送数据时只能够一位一位的发送,也就是SBUF=10是不行的智能一位一位发送也就是每次只能发送(0-9或者一个字符)并且串口调试助手接收到的数据是asii码要进行下转换,发送也要进行一下转换。这只是针对串口调试助手

    话不多说直接上代码:

     

    由于代码不方便公布所以只能上图片需要的可以私聊博主

     

     转载请标明原贴出处:https://blog.csdn.net/zj490044512

    展开全文
  • 功能:串口通信的中断方式使用,通过串口接收数据控制单片机的数码管显示电脑端发送数据(0~F),然后再回传给电脑端。 博主才疏学浅,可能会出现设计不足和错误,欢迎大家评论区交流。^ _ ^ /*********************...

    串口通信(数码管显示数据)

    使用芯片AT89S52
    功能:串口通信的中断方式使用,通过串口接收数据控制单片机的数码管显示电脑端发送数据(0~F),然后再回传给电脑端。
    博主才疏学浅,可能会出现设计不足和错误,欢迎大家评论区交流。^ _ ^

    /*******************************************************************
    此函数功能为:串口通信的中断方式使用,通过串口接收数据控制单
    片机的数码管显示电脑端发送数据,然后再回传给电脑端。
    作者:Crazy Wind      
    日期:2020.10.18
    version:1.0.0
    ********************************************************************/
    #include"reg52.h"
    #define uchar unsigned char
    #define uint unsigned int
    uchar code smgduan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf};	//段码:0~F
    uchar code smgwei[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};		//位码
    uchar y;
    /*****************************************************
    函数功能:发送数据x
    ******************************************************/
    void send_char(uchar x)
    {
    	SBUF=x;	  //SBUF是数据缓冲寄存器(暂存数据),把数据x输入到SBUF
    	while(!TI);	//等待数据发送
    	TI=0;	   //每发送8位数据TI就自动置1,需软件清零
    }
    /*****************************************************
    函数功能:串口初始化、T1作波特率发生器初始化、打开串口中断
    ******************************************************/
    void init()
    {
    	TMOD=0x20;	  //定时器1工作于8位自动重载模式, 用于产生波特率
    	TH1=0xFD;	  //波特率9600
    	TL1=0xFD;
    	SCON=0x50;	  //串口工作方式1 允许接收
    	PCON=0x00;	  //波特率不倍增
    	TR1=1;		  //启动定时器1	
    	EA=1;		  //打开总中断
    	ES=1;		  //打开串口中断
    }
    /*****************************************************
    函数功能:把接收到的数据转换成对应的段码
    ******************************************************/
    void quduanma()
    {
    	switch(y)
    	{
    		case '0':P0=smgduan[0];break;
    		case '1':P0=smgduan[1];break;
    		case '2':P0=smgduan[2];break;
    		case '3':P0=smgduan[3];break;
    		case '4':P0=smgduan[4];break;
    		case '5':P0=smgduan[5];break;
    		case '6':P0=smgduan[6];break;
    		case '7':P0=smgduan[7];break;
    		case '8':P0=smgduan[8];break;
    		case '9':P0=smgduan[9];break;
    		case 'a':P0=smgduan[10];break;
    		case 'b':P0=smgduan[11];break;
    		case 'c':P0=smgduan[12];break;
    		case 'd':P0=smgduan[13];break;
    		case 'e':P0=smgduan[14];break;
    		case 'f':P0=smgduan[15];break;
    		default:P0=smgduan[16];break;
    	}
    }
    void main()
    {
    	init();
    	P2=smgwei[0];
    	while(1);	 	
    }
    /*****************************************************
    函数功能:串口接收的中断函数
    ******************************************************/
    void TNT_Uart() interrupt 4
    {
    	if(RI==1)	 //查询是否有数据到来
    		{
    			RI=0;	 //每接收8位数据RI就自动置1,需软件清零
    			y=SBUF;	 //SBUF是数据缓冲寄存器(暂存数据),把数据输出到y
    			quduanma();
    			send_char(y);  //回传给电脑接收到的数据
    		}
    }
    
    展开全文
  • (C51学习五)单片机与PC通过串口通信

    万次阅读 多人点赞 2017-03-05 19:34:35
    2.串口模块 3.SBUF是什么 4.串口相应寄存器 5.给定波特率求定时值 6.代码实现 1.开发步骤 1.设置串口中断寄存器 2.求出给定波特率对应的T1定时器初始值(因为传统的C51是用T1定时器产生波特率的) 3.写程序 2....
  • 51单片机 串口

    千次阅读 2019-04-10 20:05:18
    51 芯片的串口可以工作在几个不同的工作模式下,其工作模式的设置就是使用SCON 寄存器。它的各个位的具体定义如下: SM0 SM1 SM2 REN TB8 RB8 TI RI SM0、SM1 为串行口工作模式设置位,这样两位可以对应进行四种...
  • 51单片机串口通信——串口设置

    千次阅读 2017-08-08 14:20:31
    51单片机串口通信如果全部把发送原理讲完的话可能要打好久几万字, 最重要的是我有些地方也没搞懂的,也讲不清楚,所以今天就直接用代码来解释…….hahahaha 串行口工作之前,应对其进行初始化,主要是设置产生...
  • 本文详细介绍了串口51单片机的ISP下载等基础知识,已经学过单片机的也可以看看,加强一下对这方面的了解。 串口 串行接口简称串口,也称串行通信接口,是采用串行通信方式的扩展接口。 ...
  • 串口和并口都是用来做数据传递的 ,串口是用连续的高低位表示数据,如0x55就是连续的01010101,高低电平间隔时间相等。具体间隔由总线速度和你配置的串口波特率有关。并口是用同一时刻几个端口的状态组合表示数据的...
  • 其实这是个51单片机串口通信的小例子,课堂上老师说你们可以去尝试弄一下,于是就去网上找一下资料,就做了这个实验。 先把一个作为主机,用来发送数据;另一个作为从机,用来接收数据。将两个程序各自烧录到对应...
  • 效果图 虚拟串口 串口调试 Proteus电路设计图 51单片机程序代码 运行
  • 51单片机程序下载与ISP

    千次阅读 2013-05-13 19:03:40
    串行接口简称串口,也称串行通信接口,是采用串行通信方式的扩展接口。 我们比较熟悉的USB接口,全名通用串行总线(Universal Serial BUS),就属于串口串行接口按电气标准及协议来分还包括UART、RS232、RS...
  • 单片机与PC机之间的通信

    千次阅读 2014-02-28 15:49:42
    51系列单片机内部的串行口具有通信的功能,该串口可以作为通信接口,利用该串行口与PC机的串行口COM1或COM2进行串行通信,将单片机采集的数据传送到PC机中,由PC机的高级语言或数据库语言对数据进行整理及统计等复杂...
  • 最近有同学在51单片机的学习过程中困扰如何使用单片机串口在上位机串口助手上输出显示的问题,其实很多开发环境都支持使用C语言里面最常用的printf函数,Keil中也不例外,不仅仅是C52、keil下其他51系列单片机如STC...
  • 51 单片机串口的扩充方法

    千次阅读 2016-01-25 11:27:10
    基本的 51 单片机有四个并行口,其中还包含了一个串行口。当接口不够用的时候,大家就会想到,使用什么外接芯片来扩充。但是,各种教材、参考书、网络文章,介绍扩充并行口的花样不少,扩充串行口的方法,几乎无人...
  • 51单片机简易烧录方法

    千次阅读 2017-06-16 22:15:34
     首先用USB转串口线连接51单片机,注意串口RX接51的TX,串口TX接51的RX,串口的地接51的地,串口的5V线先接出不用,然后打开STC官网的下载软件STC-ISP,选择好单片机型号,打开程序文件选择编译好的hex文件,点...
  • STC89C51单片机串口程序下载失败总结

    千次阅读 2020-05-12 16:03:28
    STC89C51单片机串口程序下载失败总结个人实践总结(win7 64): 电脑配置的问题 串口下载软件的问题 单片机本身的问题 硬件电路的问题关于电脑配置的问题:其他一切正常,只是在该电脑无法下载程序,可以在“禁用驱动...
  • 单片机串口通信实例

    千次阅读 2016-06-24 23:53:27
    上讲介绍并应用了单片机内部定时器和... 51 单片机内部有一个全双工串行接口。什么叫全双工串口呢?一般来说,只能接受或只能发送的称为单工串行;既可接收又可发送,但不能同时进行的称为半双工;能同时接收和发送
  • 51单片机串口通信的驱动程序

    千次阅读 2016-09-21 20:20:05
    51串口通信的简单驱动程序
1 2 3 4 5 ... 20
收藏数 12,571
精华内容 5,028
关键字:

51单片机 串口