zoukankan      html  css  js  c++  java
  • 51单片机串口通讯

    51单片机拥有一个半双工串口,分别关联P30 P31,使用串口需要注意一下几个寄存器

    1.TMOD

        串口的始终来源有四种模式,其中,移位寄存器模式不是标准串口,另外两个都是九位数据的通讯模式,一般我们不采用,一般我们采用以为起始一位停止

    八位数据的模式来进行串口通讯,这个时候需要定时器1来提供串口波特率时钟

    具体说明如下


    串口波特率计算方式如下


      其中SMOD是波特率倍增位,一般很少使用

    T1溢出率计算

     

    此处的12是因为51的周期是时钟周期分频12之后的(具体分频做什么,主要是取指,译码运行等一系列工作),由此可以计算出波特率关系


    使用串口需要这几个步骤

    1.TMOD设置TMOD,为方式2,无门控 0x20

    2.设置TH1 TL1波特率初值(SMOD不设置的情况下为0,所以一般忽略这一步,如果设置了,计算时记得加上)

    3.启动定时器TR1

    4.设置串口的工作模式,选择工作模式1 设置SM0 SM1

    5.根据需要启动REN,使能接收(也可以不使能,查询法,不过会丢数据)

    6.根据需要使能中断ES,EA

    7.如果使能了中断,记得编写中断处理函数

    注意:

      如果使能了接收中断,那么在串口中断中,要判断到底是发生了接收中断还是发送中断,因为两个中断共用中断源,依靠TI RI识别



    51单片机使用PRINTF

       keil内置了编写好的printf函数库,默认情况下,直接包含<stdio.h>就可以使用,但是,这个printf和串口中断最好不要一起工作,也就是说printf工作的时候串口中断发生,会使得printf很慢,因为printf发送的时候会频繁进入中断,有一个比较好的办法是重载putchar,将之前putchar判定TI的位置修改为自己的判定.

       另外,在中断中不要使用printf,这会导致系统库函数printf出现重入,系统挂掉就很正常(类似于malloc也不要用)


    示例程序如下

    #include "uart.h"
    
    
    u8 Uart0_Send_Ready;
    
    char putchar (char c)
    {
        if (c == '
    ')
        {
            while (!Uart0_Send_Ready);
            Uart0_Send_Ready = 0;
            SBUF = 0x0d;                         /* output CR  */
        }
        while (!Uart0_Send_Ready);
        Uart0_Send_Ready = 0;
        return (SBUF = c);
    }
    
    
    
    
    //51单片机最好使用9600波特率,安全稳定
    
    #define BAUD 9600
    
    #define INIT_VALUE 256-(XTAL/(384*BAUD))
    
    static txSendOver = 0;
    
    void UartInit(void)//default baud is 9600 is nore safe baud
    {
    	u8 value = TMOD;
    	value &= 0x0f;
    	value |= 0x20;//使用模式2
    	TMOD = value;
    	TH1 = 0xfd;//
    	TL1 = 0xfd;
    	//不打开中断
    	TR1 = 1;
    	SM0 = 0;//8λuart
    	SM1 = 1;
    	REN = 1;//使能接收
    	EA=1;   //打开总中断
    	ES=1;		//打开串口中断
    	
    }
    
    
    void UartSendChar(u8 value)
    {
    	txSendOver = 1;
    	SBUF = value;
    	while(txSendOver);
    }
    
    void UartSendBuffer(u8* buffer,u8 length)
    {
    	u8 i = 0;
    	for(i = 0; i < length; i++)
    	{
    		UartSendChar(*(buffer+i));
    	}
    }
    
    void UartInt() interrupt 4
    {
    	u8 dat;
    	if(TI == 1)
    	{
    		Uart0_Send_Ready = 1;
    		TI = 0;
    		
    		txSendOver = 0;
    	}
    	if(RI == 1)
    	{
    		RI = 0;
    		dat=SBUF; 
    	}
    }

    记得自己添加stdio.h的文件包含


  • 相关阅读:
    LINQ -2015-04-27
    wireshark的安装
    c#中的classes和objects一些知识【1】
    初学C#,用vs去开始hello world!
    file_get_contents HTTP request failed! Internal Server Error
    验证码二(验证码使用)
    接口调用 POST
    接口调用 GET方式
    百度地图改标注样式
    Linux-常用命令
  • 原文地址:https://www.cnblogs.com/dengxiaojun/p/4279452.html
Copyright © 2011-2022 走看看