历史上的今天
返回首页

历史上的今天

今天是:2024年10月19日(星期六)

正在发生

2021年10月19日 | 如何驱动51单片机串口(uart通信)

2021-10-19 来源:eefocus

使用51单片机上uart通信的驱动程序,软件特性可以在proteus上仿真,使用51单片机定时器T1溢出率做uart波特率时基,采用12MHz晶振,uart波特率采用4800。下面直接上代码:


uart驱动接口

uart模块向外提供的接口,主要是用于初始化uart和发送数据的接口。


void uart_init(void);  // 初始化串口

void uart_deinit(void);  // 串口去初始化

void uart_send_data(u8 dat);  // 串口发送

void uart_send_num(s32 num);  // 串口发送数字

void uart_send_str(string str);  // 串口发送字符串

u32 uart_str_to_num(string str);  // 字符串转数字

void test_uart(void);  // uart测试代码


初始化uart

51单片机采用12MHz晶振,设置uart异步通信,无校验,停止位1位,波特率4800。定时器工作在方式二,计时溢出后自动重载初值。


/*******************************************************************************

* 函 数 名         : uart_init

* 函数功能         : 初始化串口

* 输    入         : void

* 输    出         : void

* 说    名         : none

*******************************************************************************/

void uart_init(void)  // 初始化串口

{

    SCON = 0x50;  // 设置为工作方式1

    TMOD |= 0x20;  // 设置计数器工作方式2

    PCON = 0x80;  // 波特率加倍

    TH1 = 0xf3;   // 计数器初始值设置,波特率4800

    TL1 = 0xf3;

    IE |= 0x90;   // 打开接收中断

    TR1 = 1;  // 打开计数器

}


uart发送数据

uart发送一个字节的数据。此函数接口是实现发送字符串和数字的基础。


/*******************************************************************************

* 函 数 名         : uart_send_data

* 函数功能         : 串口发送

* 输    入         : dat:待发数据

* 输    出         : void

* 说    名         : none

*******************************************************************************/

void uart_send_data(u8 dat)  // 串口发送

{

    SBUF = dat;          // 将数据放入到发送寄存器

    while(!TI);          // 等待发送数据完成

    TI = 0;              // 清除发送完成标志位

}


uart发送数字

uart发送数字,现将数字编码为ascii码,在通过uart_send_data接口送出。


/*******************************************************************************

* 函 数 名         : uart_send_num

* 函数功能         : 串口发送数字

* 输    入         : num:数字

* 输    出         : void

* 说    名         : none

*******************************************************************************/

void uart_send_num(s32 num)  // 串口发送数字

{

    u8 i;

    u8 dat[10] = { 0 };  // 不能使用malloc


    if (num < 0) {

        uart_send_data('-');

        num = -num;

    }

    for (i = 0; num; i++) {

        dat[i] = (num % 10 + '0');

        num /= 10;

    }

    for (; i; i--) {

        uart_send_data(dat[i - 1]);

    }

}


uart发送字符串

依次调用uart_send_data即可。


/*******************************************************************************

* 函 数 名         : uart_send_str

* 函数功能         : 串口发送字符串

* 输    入         : str:字符串

* 输    出         : void

* 说    名         : none

*******************************************************************************/

void uart_send_str(string str)  // 串口发送字符串

{

    for (; (*str) != ''; str++) {

        uart_send_data(*str);

    }

}


字符串转数字

将字符串装换为数字返回。


/*******************************************************************************

* 函 数 名         : uart_str_to_num

* 函数功能         : 字符串转数字

* 输    入         : str:字符串

* 输    出         : u32:转换结果

* 说    名         : none

*******************************************************************************/

u32 uart_str_to_num(string str)  // 字符串转数字

{

    u32 num = 0;


    for (; (*str) != ''; str++) {

        if (((*str) >= '0') && ((*str) <= '9')) {

            num = num * 10 + ((*str) - '0');

        } else {

            break;

        }

    }


    return num;

}


附录 - uart驱动(uart.h)

#ifndef __UART_H__

#define __UART_H__


#include "include.h"


#define START_MARK ':'   // 指令结束标记


void uart_init(void);  // 初始化串口

void uart_deinit(void);  // 串口去初始化

void uart_send_data(u8 dat);  // 串口发送

void uart_send_num(s32 num);  // 串口发送数字

void uart_send_str(string str);  // 串口发送字符串

void uart_send_time(void);  // 串口发送本地时间

u32 uart_str_to_num(string str);  // 字符串转数字

void test_uart(void);  // uart测试代码


#endif


附录 - uart驱动(uart.c)

#include

#include "uart.h"

#include "lcd1602.h"

#include "clock.h"


/*******************************************************************************

* 函 数 名         : uart_init

* 函数功能         : 初始化串口

* 输    入         : void

* 输    出         : void

* 说    名         : none

*******************************************************************************/

void uart_init(void)  // 初始化串口

{

    SCON = 0x50;  // 设置为工作方式1

    TMOD |= 0x20;  // 设置计数器工作方式2

    PCON = 0x80;  // 波特率加倍

    TH1 = 0xf3;   // 计数器初始值设置,波特率4800

    TL1 = 0xf3;

    IE |= 0x90;   // 打开接收中断

    TR1 = 1;  // 打开计数器

}


/*******************************************************************************

* 函 数 名         : uart_deinit

* 函数功能         : 串口去初始化

* 输    入         : void

* 输    出         : void

* 说    名         : none

*******************************************************************************/

void uart_deinit(void)  // 串口去初始化

{

    TR1 = 0;  // 关闭计数器

    IE &= 0x8f;   // 关闭接收中断

    SCON = 0x00;  // 设置为工作方式1

    TMOD &= 0xdf;

    PCON = 0x00;  // 波特率加倍

    TH1 = 0xf3;   // 计数器初始值设置,波特率4800

    TL1 = 0xf3;

}


/*******************************************************************************

* 函 数 名         : uart_send_data

* 函数功能         : 串口发送

* 输    入         : dat:待发数据

* 输    出         : void

* 说    名         : none

*******************************************************************************/

void uart_send_data(u8 dat)  // 串口发送

{

    SBUF = dat;          // 将数据放入到发送寄存器

    while(!TI);          // 等待发送数据完成

    TI = 0;              // 清除发送完成标志位

}


/*******************************************************************************

* 函 数 名         : uart_send_num

* 函数功能         : 串口发送数字

* 输    入         : num:数字

* 输    出         : void

* 说    名         : none

*******************************************************************************/

void uart_send_num(s32 num)  // 串口发送数字

{

    u8 i;

    u8 dat[10] = { 0 };  // 不能使用malloc


    if (num < 0) {

        uart_send_data('-');

        num = -num;

    }

    for (i = 0; num; i++) {

        dat[i] = (num % 10 + '0');

        num /= 10;

    }

    for (; i; i--) {

        uart_send_data(dat[i - 1]);

    }

}


/*******************************************************************************

* 函 数 名         : uart_send_str

* 函数功能         : 串口发送字符串

* 输    入         : str:字符串

* 输    出         : void

* 说    名         : none

*******************************************************************************/

void uart_send_str(string str)  // 串口发送字符串

{

    for (; (*str) != ''; str++) {

        uart_send_data(*str);

    }

}


/*******************************************************************************

* 函 数 名         : uart_send_time

* 函数功能         : 串口发送本地时间

* 输    入         : void

* 输    出         : void

* 说    名         : none

*******************************************************************************/

void uart_send_time(void)  // 串口发送本地时间

{

    uart_send_str("time:rn");

    uart_send_num(time.year);

    uart_send_data('-');

    uart_send_num(time.month);

    uart_send_data('-');

    uart_send_num(time.day);

    uart_send_data(' ');

    uart_send_num(time.hour);

    uart_send_data(':');

    uart_send_num(time.miunte);

    uart_send_data(':');

    uart_send_num(time.second);

    uart_send_data(' ');

推荐阅读

史海拾趣

Hosiden Corporation公司的发展小趣事

近年来,Hosiden在技术创新方面取得了显著成果。特别是在汽车市场,公司积极参与并推动了MIPI A-PHY标准的验证与应用。Hosiden与Valens Semiconductor等领先企业合作,完成了其连接器和电缆对Valens VA7000芯片组的验证,这是市场上首个符合MIPI A-PHY的芯片组。这一里程碑式的成就不仅展示了Hosiden在技术创新方面的实力,也进一步巩固了其在汽车电子市场中的领先地位。

DZUS公司的发展小趣事

随着公司实力的增强,DZUS公司开始拓展国际市场。通过参加国际展览、与海外客户建立合作关系等方式,公司逐渐打开了国际市场的大门。同时,公司还针对不同国家和地区的市场需求,推出了定制化的产品和服务。这些举措使DZUS公司的品牌知名度和市场份额不断提升。

电连(ECT)公司的发展小趣事

为了进一步扩大市场份额,ECT积极推进国际化战略。截止2022年初,公司在全球共设立23个分支机构,覆盖了中国台湾、中国香港、韩国、日本、泰国、越南、美国等国家和地区。通过国际化战略的实施,ECT不仅成功将产品推向全球市场,也提升了公司的国际影响力和竞争力。

Alpha Wire公司的发展小趣事

随着汽车智能化的发展,ECT看到了车载连接器市场的巨大潜力。从2013年开始,公司开始布局车载连接器领域,并成功开发出多款适用于不同车型和场景的车载连接器产品。这一拓展不仅为ECT带来了新的增长点,也进一步巩固了公司在电子连接器行业的领先地位。

Eastron Corp公司的发展小趣事

Eastron Corp一直重视人才的培养和引进。公司建立了完善的人才培养和激励机制,鼓励员工不断学习和创新。同时,Eastron还积极引进国内外优秀人才,为公司的发展注入新的活力。正是凭借一支高素质、专业化的团队,Eastron在电子行业中不断取得新的突破。

东晨(DC)公司的发展小趣事

在电子行业中,合作与竞争并存。东晨(DC)公司善于在合作中寻求共赢,与产业链上下游企业建立了紧密的合作关系。同时,公司也积极参与市场竞争,通过不断创新和优化产品,提高市场竞争力。在与国内外同行的竞争中,东晨(DC)公司始终保持着领先地位,赢得了市场的广泛认可。

问答坊 | AI 解惑

遇到了一个诡异的问题。

VC代码移植到EVC4.0.编译没问题,但画面不能正常显示。图形在ONDRAW函数里画的,2万行左右。 于是我一点点的添加,开始是正常的,后来就不正常了,有行数限制? 有时候多初始化一个矩形就不行,有时候把矩形初始化赋值的代码注释起来,就能继续添 ...…

查看全部问答>

做基于ARM的嵌入式LINUX开发应届生工资应该给多少?

做基于ARM的嵌入式LINUX开发应届生在江浙一带工资应该给多少? 能力还可以吧,说不上好也说不上坏!~ …

查看全部问答>

不能正确读取开关量

连接如图,用128的pe口读取八个开关,如果全部不连通没有问题,如果全部接通也没有问题,问题是:如果只接通SW8,则PE02和PE03均为零,如果接通SW6,则PE04和PE05均为零,这是为什么呀??245有问题?还是?…

查看全部问答>

【LaunchPad学习】 MSP430G2452电容测量问题

想通过P1.1测量电容量,可是代码跑起来后,在不同时刻meas_cnt的值却始终为0。 使用官方的msp430g2xx2_pinosc_01.c代码测量到的meas_cnt也始终为0.p1.0,p1.6的LED不断闪烁。 上面是修改后的代码,在meas_cnt处设置了断点。 //**************** ...…

查看全部问答>

哈哈~突然发现自己太有才了有木有啊,3个IO口控制一个12864+4个LED~上图

如题如题。。。 一片小小的244芯片帮了我的大忙啊,说多无用,有图有真相。…

查看全部问答>

电路在空载时出现的问题

请教大家,电路在空载时为什么会产生间隙震荡呢?…

查看全部问答>

信号放大中遇到的问题

谁能告诉我做信号放大在什么条件下需要多个电路?谢谢了,嘿嘿…

查看全部问答>

请教各位OrCAD Capture CIS的一个小问题

不是很熟啊,小问题请教一下 制作元器件 用SpreadSheet放置管脚 Top和Right方向管脚序号 左到右,上到下顺序,如何改成右到左和下到上啊。没查到。 谢谢。…

查看全部问答>

为什么我的CCS 5.2不能退出DEBUG ?

调试目标C2000,可以进入DEBUG模式,可以进行正常调试,但是,退出就不行了,一点退出(就是那个红方块)就死着不动。只有关闭了。 每次这样很麻烦。且,原来编译时的状态不保存。…

查看全部问答>

5438跑到24MHz+uart9600+uart115200

找了各种资料,总觉得5438这么多资源,只用8M的外部晶振太慢,内部刚好有dco,调试了一下最后跑到24MHz。外加了ssd1289液晶+ads7843触摸+uartA0。115200+uartA1.9600 下附代码 #include #include\"tft.h\" #include\"cc1101.h\" #include\"gps ...…

查看全部问答>