串口通信(SBUF&代码&原理详解)

基本概念

前言:
时钟对于单片机来说是非常重要的,它能为单片机提供一个稳定的机器周期从而使系统能够正常工作。它就像我们人类的心脏一样重要,一但有了问题那么系统就会崩溃。我们在使用单片机的时候,常常会使用默认的时钟频率,然而在一些特殊的场合(例如串口通讯或者实时时钟),则需要特殊的时钟频率,这时芯片自带的振荡器就无法满足我们的需求。这个时候,就可以选择外部晶振作为时钟源。

波特代表每秒的调制数,它是对符号传输速率的一种度量,n波特即指每秒传输n个符号(传符号率)
人话:波特率就是发送二进制数据位的速率,习惯上用 baud 表示,即我们发送一位二进制数据
的持续时间=1/baud。
有关波特率的设置:
在这里插入图片描述可以利用stc_isp生成软件,生成代码,注意使用的串口助手波特率设置一定要和此时生成代码的波特率一致。

在通信之前,通信双方的波特率需要设置相同,才能实现正常通信。

时钟频率的理解:
RC振荡器与晶振的区别
在这里插入图片描述
在这里插入图片描述

我们利用stc-isp会设置用户运行的内部时钟RC的频率,一般来说蓝桥杯是12MHZ,但对于串口通信来说11.0592Mhz可以是波特率计算中证书更多,误差更小。

在这里插入图片描述
利用软件,我们设置为12分频串口通信,同时Fosc/12
在这里插入图片描述对于初值的计算,是有TL1 = 256 - FOSC / 12 / 2 baud

读取数据手册

在这里插入图片描述

在这里插入图片描述

串口中断

在这里插入图片描述
由上图,我们知道串口中断号为4

代码讲解

void uart_sendstr(uint8 *str)   //串口发送一般用查询
{
	uint8 *s;    //副本,定义一个指针,指向str的一个字符
	s = str;     //s指向str的第一个字符
	while(*s != '\0')  //s是一个指针,与*结合说明,s指针指向的地址里的内容
	{
		SBUF = *s;  //s这个地址里的内容发送给接受缓冲器
		while(TI == 0); //等待数据发送完毕    因为TI=1表示数据发送完毕   SBUF在左边说明是接受缓冲区
			TI = 0;  //手动TI置0
			s++;    //s指向的地址++
	}
}
                                                                                                                                                                                                                                    一般发送数据是用查询方式,也就是在main函数里一直循环我们的发送代码。

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

void UART_Interrupt(void) interrupt 4
{
	if(RI)			//如果接收到
	{
		RI = 0;		//手动清零接收中断标志位
		SBUF = SBUF+1;	//接收到后+1再发送回去,左边是发送SBUF右边的SBUF就是接收缓冲区的数据,是电脑发送给单片机,
	}
	
	if(TI)			//如果发送完毕
	{
		TI = 0;		//手动清零发送中断标志位
	}
}

串行发送数据时,CPU向SBUF写入数据,此时99H表示串行口的发送缓冲寄存器;
串行接收数据时,CPU从SBUF读出数据,此时99H表示串行口的接收缓冲寄存器。

串口调试助手的实质就是利用电脑上的 UART 通信接口,发送数据给我们的单片机,也
可以把我们的单片机发送的数据接收到这个调试助手界面上。

由上面两段话,我们可以了解到接收缓冲区和发送缓冲区的作用(信息发送方向):
在这里插入图片描述
在这里插入图片描述

  • 31
    点赞
  • 105
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个基于51单片机串口通信的密码锁代码,可以供参考: ```C #include <reg51.h> #define PASSWORD "123456" // 设置密码为 123456 #define PASSWORD_LEN 6 sbit LED = P1^0; // 锁状态指示灯 char password_input[PASSWORD_LEN]; // 存储用户输入的密码 int password_index = 0; // 当前用户输入密码的字符位置 int password_correct = 0; // 用户输入的密码是否正确 void init_serial() { TMOD = 0x20; // 定时器1工作在模式2 TH1 = 0xFD; // 波特率9600,定时器1初始值为65536 - (11.0592MHz / 12 / 32 / 9600) = 253 TL1 = 0x53; SCON = 0x50; // 8位数据,可变波特率,启用接收 TR1 = 1; // 启动定时器1 } void send_char(char c) { SBUF = c; while (!TI); TI = 0; } void send_string(char *s) { while (*s) { send_char(*s++); } } void main() { init_serial(); while (1) { if (password_correct) { // 用户输入的密码正确 LED = 0; // 开锁 send_string("unlock\r\n"); password_correct = 0; password_index = 0; } } } void interrupt_serial() interrupt 4 { if (RI) { // 接收到一个字符 RI = 0; char c = SBUF; password_input[password_index++] = c; if (password_index == PASSWORD_LEN) { // 用户已经输入完整个密码 if (strcmp(password_input, PASSWORD) == 0) { // 用户输入的密码与预设的密码一致 password_correct = 1; } else { // 密码错误 password_index = 0; LED = 1; // 关锁 send_string("wrong password\r\n"); } } } } ``` 这个代码使用了串口通信来接收用户输入的密码,并将用户输入的密码存储在一个字符数组中。如果用户输入的密码与预设的密码一致,则开启锁状态指示灯并发送一个 "unlock" 字符串;否则关闭锁状态指示灯并发送一个 "wrong password" 字符串。注意,在实际应用中需要进行更多的安全考虑和实现。同时,要注意串口通信可能会受到干扰和攻击,需要进行一定的防范措施。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值