C51单片机基础之串口编程实战

news2024/11/13 4:34:07

目录

一、串口编程寄存器分析

1、PCON : 电源控制寄存器

2、SCON:串行控制寄存器

二、自己实现串口初始化编程

三、发送一串字符串给到PC端编程

四、PC发送指令控制LED编程

五、串口中断实时控制LED编程

1、串口中断的中断号:interrupt4

2、串口中断相关的寄存器

3、串口中断实时控制LED编程

六、串口控制的ASSII避坑

七、串口支持单词型指令控制


一、串口编程寄存器分析

1、PCON : 电源控制寄存器

SMOD:波特率选择位

SMOD = 0; 串口方式1,2,3时,波特率正常

SMOD = 1;串口方式1,2,3时,波特率加倍

例如: PCON &= 0x7F;        //波特率不倍速

7F转换成二进制后是 0111   1111,意思是高位清零,其他位不变,因为如上图SMOD在高位,高位要清零,所以SMOD = 0,波特率属于正常倍数

2、SCON:串行控制寄存器

REN:允许/禁止串行接收控制位。即REN=1为允许串行接收状态 ,REN=0,则禁止接收

TI: 发送中断请求标志位。即TI=1,向主机请求中断,响应中断后必须用软件复位,即TI=0

例如:SCON = 0x50;        //8位数据,可变波特率

50转换成二进制后是0101  0000,带到SCON寄存器中就是 SM0 = 0、SM1 = 1,选择工作方式1,然后REN = 1,允许串行接收控制位

总结一下使用串口,需要用到的寄存器:

REN:允许/禁止串行接收控制位。即REN=1为允许串行接收状态

TI:发送中断请求标志位;TI = 1  指发送数据

RI:接收中断请求标志位;RI = 1 指接收到数据,硬件置1

二、自己实现串口初始化编程

#include "reg52.h"

sfr AUXR = 0x8E;
void UartInit(void)		//9600bps@11.0592MHz
{
	AUXR = 0x01;   //降低时钟对外界的辐射
	SCON = 0x40;   //串行口寄存器工作模式选择方式1,RNE=0,为串行禁止接收状态
	TMOD &= 0x0F;  //定时器1工作方式位8位自动重装
	TMOD |= 0x20;
	TH1 = 0xFD; 
	TL1 = 0xFD;   //9600波特率的初值
	TR1 = 1;      //启动定时器
}

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void main()
{
	char data_msg = 'a';
	//配置C51串口的通信方式
	UartInit();
	while(1){
		Delay1000ms();
		//往发送缓冲区写入数据,就完成数据的发送
		SBUF = data_msg;
	}
}

三、发送一串字符串给到PC端编程

#include "reg52.h"

sfr AUXR = 0x8E;
void UartInit(void)		//9600bps@11.0592MHz
{
	AUXR = 0x01;   //降低时钟对外界的辐射
	SCON = 0x40;   //串行口寄存器工作模式选择方式1,RNE=0,为串行禁止接收状态
	
	TMOD &= 0x0F;  //定时器1工作方式位8位自动重装
	TMOD |= 0x20;
	
	TH1 = 0xFD; 
	TL1 = 0xFD;   //9600波特率的初值
	TR1 = 1;      //启动定时器
	
}

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay10ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 18;
	j = 235;
	do
	{
		while (--j);
	} while (--i);
}

void sendByte(char data_msg){
	SBUF = data_msg;
	while(!TI);   //智能延时,靠硬件延时
	TI = 0;
}

void sendString(char* str){

	while(*str != '\0'){
		sendByte(*str);
		str++;
	}
}

void main()
{

	//配置C51串口的通信方式
	UartInit();
	while(1){
		Delay1000ms();
		//往发送缓冲区写入数据,就完成数据的发送
		sendString("hello world !\r\n");
	}
	
}

四、PC发送指令控制LED编程

#include "reg52.h"

sbit D5 = P3^7;

sfr AUXR = 0x8E;
void UartInit(void)		//9600bps@11.0592MHz
{
	AUXR = 0x01;   //降低时钟对外界的辐射
	SCON = 0x50;   //串行口寄存器工作模式选择方式1,RNE=1,为串行允许接收状态
	
	TMOD &= 0x0F;  //定时器1工作方式位8位自动重装
	TMOD |= 0x20;
	
	TH1 = 0xFD; 
	TL1 = 0xFD;   //9600波特率的初值
	TR1 = 1;      //启动定时器
	
}

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void sendByte(char data_msg){
	SBUF = data_msg;
	while(!TI);   //智能延时,靠硬件延时
	TI = 0;
}

void sendString(char* str){

	while(*str != '\0'){
		sendByte(*str);
		str++;
	}
}

void main()
{
	char cmd;
	D5 = 1;
	//配置C51串口的通信方式
	UartInit();
	while(1){
		Delay1000ms();
		//往发送缓冲区写入数据,就完成数据的发送
		sendString("hello world !\r\n");
		//怎么知道收到数据,查询RI的值,如果RI是1(收到数据后由硬件置1)
		if(RI == 1){
			RI = 0;
			cmd = SBUF;
			if(cmd == 'o'){
				D5 = 0;   //D5灯亮
			}
			if(cmd == 'c'){
				D5 = 1;   //D5灯灭
			}
		}		
	}
}

五、串口中断实时控制LED编程

1、串口中断的中断号:interrupt4

2、串口中断相关的寄存器

ES:串行口1中断允许位。ES=1,允许串行口1中断;ES=0,禁止串行口1中断

EA:CPU的总中断允许控制位,EA=1,CPU开放中断,EA=0,CPU屏蔽所有的中断申请

3、串口中断实时控制LED编程

#include "reg52.h"

sbit D5 = P3^7;

sfr AUXR = 0x8E;
char cmd;
void UartInit(void)		//9600bps@11.0592MHz
{
	AUXR = 0x01;   //降低时钟对外界的辐射
	SCON = 0x50;   //串行口寄存器工作模式选择方式1,RNE=1,为串行允许接收状态
	
	TMOD &= 0x0F;  //定时器1工作方式位8位自动重装
	TMOD |= 0x20;
	
	TH1 = 0xFD; 
	TL1 = 0xFD;   //9600波特率的初值
	TR1 = 1;      //启动定时器
	
	EA = 1;       //总中断寄存器,开启总中断
	ES = 1;       //开启串口中断
	
}

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay10ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 18;
	j = 235;
	do
	{
		while (--j);
	} while (--i);
}

void sendByte(char data_msg){
	SBUF = data_msg;
	while(!TI);   //智能延时,靠硬件延时
	TI = 0;
}

void sendString(char* str){

	while(*str != '\0'){
		sendByte(*str);
		str++;
	}
}

void main()
{
	D5 = 1;
	//配置C51串口的通信方式
	UartInit();
	while(1){
		Delay1000ms();
		//往发送缓冲区写入数据,就完成数据的发送
		sendString("hello world !\r\n");
		//怎么知道收到数据,查询RI的值,如果RI是1(收到数据后由硬件置1)		
	}
}

void	Uart_Handler()	interrupt 4
{
	if(RI == 1){     //中断处理函数中,对于接收中断的响应  
		RI = 0;   //清除接收中断标志位
		cmd = SBUF;
		if(cmd == 'o'){
			D5 = 0;  //点亮D5
		}
		if(cmd == 'c'){
			D5 = 1;  //熄灭D5
		}
	}
	if(TI);
}

六、串口控制的ASSII避坑

1、在使用串口进行数据发送和接收时,我们一般选用文本模式进行数据的发送和接收

文本模式:收到的是字母(0-9,a-z,A-Z等其他符号)
HEX模式:收到的是十六进制;
不做任何类型转换输入时,系统会自动默认为是十进制
例如:
SBUF=33
调为文本模式,显示为**!;
调为HEX模式,则显示为
21**

七、串口支持单词型指令控制

static:函数调用的时候,如果没有static,那在每一次调用这个函数时,都会执行这个参数,有了static关键字,在每一次调用这个函数时,这个参数只会执行一次

#include "reg52.h"
#include <stdio.h>
#include <string.h>
#define SIZE 12
sbit D5 = P3^7;

sfr AUXR = 0x8E;
char cmd[SIZE];
void UartInit(void)		//9600bps@11.0592MHz
{
	AUXR = 0x01;   //降低时钟对外界的辐射
	SCON = 0x50;   //串行口寄存器工作模式选择方式1,RNE=1,为串行允许接收状态
	
	TMOD &= 0x0F;  //定时器1工作方式位8位自动重装
	TMOD |= 0x20;
	
	TH1 = 0xFD; 
	TL1 = 0xFD;   //9600波特率的初值
	TR1 = 1;      //启动定时器
	
	EA = 1;       //总中断寄存器,开启总中断
	ES = 1;       //开启串口中断
	
}

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay10ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 18;
	j = 235;
	do
	{
		while (--j);
	} while (--i);
}

void sendByte(char data_msg){
	SBUF = data_msg;
	while(!TI);   //智能延时,靠硬件延时
	TI = 0;
}

void sendString(char* str){

	while(*str != '\0'){
		sendByte(*str);
		str++;
	}
}

void main()
{
	
	D5 = 1;
	//配置C51串口的通信方式
	UartInit();
	while(1){
		Delay1000ms();
		//往发送缓冲区写入数据,就完成数据的发送
		sendString("hello world !\r\n");
		//怎么知道收到数据,查询RI的值,如果RI是1(收到数据后由硬件置1)		
	}
}

void	Uart_Handler()	interrupt 4
{
	static int i = 0;   //静态变量,被初始化一次
	if(RI == 1){     //中断处理函数中,对于接收中断的响应  
		RI = 0;   //清除接收中断标志位
		cmd[i] = SBUF;
		i++;
		if(i == SIZE){
			i = 0;
		}
		if(strstr(cmd,"en")){
			D5 = 0;  //点亮D5
			i = 0;
			memset(cmd,'\0',SIZE);
			
		}
		if(strstr(cmd,"se")){
			D5 = 1;  //熄灭D5
			i = 0;
			memset(cmd,'\0',SIZE);
		}
	}
	if(TI);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/141712.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Apache Doris Join 实现与调优实践|未来源码

推荐语&#xff1a; SQL 的支持力度和粒度&#xff0c;已经作为今天所有大数据计算引擎的重要衡量标准之一&#xff0c;而 SQL 的所有操作&#xff0c;可以分为简单操作&#xff08;如 where、limit等 filter 操作&#xff09;和复杂操作&#xff08;groupby、join 等聚合操作&…

SpringCloud微服务项目实战 - 3.App端文章

经历了新冠疫情始末&#xff0c;之后&#xff0c;多出门走走&#xff0c;看看山&#xff0c;看看海&#xff0c;吃好吃的 系列文章目录 项目搭建App登录及网关App文章 文章目录系列文章目录一、文章列表1. 数据库⑴. 导入文章数据库⑵. 表结构分析①. ap_article 文章基本信息…

MySQL慢SQL探究

文章目录前言1、慢SQL捕获慢查询追踪配置方式2、情况分析为什么查询会慢&#xff1f;2.1 SQL执行计划分析explain执行计划分析PROFILE分析OPTIMIZER_TRACE分析3、引擎参数配置分析I/O性能分析MySQL I/O参数其他原因分析网络抖动单表数据量过大总结前言 我们在日常开发中&#…

GeoServer搭建私有地图服务,Cesium引擎加载。

一、安装JDK 1、安装GeoServer是基于Java的环境&#xff0c;所以需要先装Jdk环境。 2、前往官网下载Java SE 3、下载GeoServer 1、前往官网下载最新稳定版 2、安装GeoServer 二、发布地图服务 1、启动geoserver 找到安装目录&#xff0c;bin/下的startup.bat,双击执行…

PF-Net源码详解

代码及数据见最后 1.参数配置 参数配置使用默认参数即可,但是windows操作系统下,需要将--workers设置为0. 2.数据准备 PF-Net将不完整的点云做输入,并预测其缺失部分。同时,我们可以从整体流程看到,输入有三个尺度,通过最远点采样进行构建,预测的输出也有三个尺度。数…

MySQL:SQL通用语法、SQL分类、DDL、DML、DQL、DCL

一.SQL通用语法 SQL语句可以单行或多行书写&#xff0c;以分号结尾&#xff1b;SQL语句可以使用空格/缩进来增强语句的可读性&#xff1b;MySQL数据库SQL语句不区分大小写&#xff0c;关键字建议大写&#xff1b;注释&#xff1a; 单行&#xff1a;--或#多行&#xff1a;/* …

Spring AOP 面向切面编程

1.AOP是什么我们之前学过 OOP 面向对象编程, 那么 AOP 是否就比 OOP 更牛逼呢? 是否也是面向过程到面向对象这种质的跨越呢? 其实不是, 它和 OOP 思想是一种互补的关系, 是对 OOP 思想的一种补充.AOP (Aspect Oriented Programming) : 面向切面编程, 它是一种思想, 它是对某一…

Arrays数组

1.Arrays.toString()方法:输出数组内容 2.Arrays.sort()方法:给数组排序&#xff0c;默认升序 对其他对象数组进行排序 一个对象数组&#xff0c;排序算法需要重复比较数组中的元素。不同的类比较元素的规则是不同的&#xff0c;但是排序算法只应该调用类提供的比较方法&#…

netty中channelHandler实现原理及最佳实践|极客星球

为持续夯实MobTech袤博科技的数智技术创新能力和技术布道能力&#xff0c;本期极客星球邀请了企业服务研发部工程师梁立从 TCP 的粘包/半包、 Netty 处理粘包/半包及源码分析、 开源项目对 channelHandler最佳实践三方面对《netty 中channelHandler的原理与最佳实践》进行了全面…

【Ctfer训练计划】——(九)

作者名&#xff1a;Demo不是emo 主页面链接&#xff1a;主页传送门创作初心&#xff1a;舞台再大&#xff0c;你不上台&#xff0c;永远是观众&#xff0c;没人会关心你努不努力&#xff0c;摔的痛不痛&#xff0c;他们只会看你最后站在什么位置&#xff0c;然后羡慕或鄙夷座右…

Python+Selenium4元素定位_web自动化(3)

目录 0. 上节回顾 1. 八大定位 2. 定位器 3. CSS选择器 4. XPath选择器 4.1. XPath语法 4.2. XPath 函数 5. 相对定位 5.1 XPath 中的相对定位【重点】 5.1.1 相对路径 5.1.2 轴 5.2 selenium4 中的相对定位 总结 0. 上节回顾 浏览器的一般操作 浏览器的高级操作…

【sciter】:JSX 组件实现数据持久化

# 原理 组件数据持久化指的是:重新加载组件后,能否将重新加载前组件所存在的数据,在重新加载后数据依旧保存在组件中。 组件数据持久化实现原理:将每次更新组件数据同步到 Storage 中。并且监听组件重新加载(刷新),在刷新前将 Storage 关闭(确保数据不丢失)。当加载…

idea中添加git使用时文件不同颜色,标签不同颜色,代码不同颜色代表的含义

文章目录文件的颜色标签的颜色合并代码时不同颜色区块的含义文件的颜色 绿色——已经加入控制暂未提交&#xff1b; 红色——未加入版本控制&#xff1b;自己建立新文件后就是红色的&#xff0c;出现红色的一定要Add到git中&#xff0c;不然不能上传到远程仓库 蓝色——加入&am…

关于markdown相关语法的学习

众所周知&#xff0c;一个好的项目需要搭配一个好的项目说明&#xff0c;就行吃饺子需要蘸醋一样&#xff0c;没有醋的饺子&#xff0c;你仅仅吃掉了他的肉体&#xff0c;而得不到他的灵魂。下面开始吃饺子&#xff0c;不对&#xff0c;是开始学习markdown文件的基础语法&#…

在采购管理过程中使用技术有什么好处?

采购过程不总是简单直接的&#xff0c;人工采购过程非常耗费人力和时间&#xff0c;并且涉及大量文书工作。另一方面&#xff0c;当你在采购过程中使用技术时&#xff0c;比如使用SRM采购管理系统&#xff0c;会节省很多时间&#xff0c;使整个过程变得更加简单和轻松。 在讨…

Homekit智能家居创意DIY之智能吸顶灯

买灯要看什么因素 好灯具的灯光可以说是家居的“魔术师”&#xff0c;除了实用的照明功能外&#xff0c;对细节的把控也非常到位。那么该如何选到一款各方面合适的灯呢&#xff1f; 照度 可以简单理解为清晰度&#xff0c;复杂点套公式来说照度光通量&#xff08;亮度&#…

【达梦8】vm 虚拟机centos 7 安装达梦8 数据库

目录准备下载安装包版本选择安装前准备【登录root用户】创建用户【登录root用户】设置限制资源配置【登录dmdba用户】上传iso文件挂载iso创建安装路径开始安装【登录dmdba用户】安装【登录dmdba用户】初始化实例初始化注意事项开始初始化启动数据库启动方式1 &#xff08;推荐&…

Linux oom机制

Linux oom机制前言1 内存回收2 OOM基本原理2.1 虚拟内存OOM2.2 物理内存OOM3 oom配置参数3.1 panic_on_oom3.2 oom_kill_allocating_task3.3 oom_dump_tasks4 安卓LMK简介5 总结前言 Linux oom是由于内存泄漏或者内存使用不合理而导致的问题。 在讲OOM之前&#xff0c;我们先…

数据库,计算机网络、操作系统刷题笔记25

数据库&#xff0c;计算机网络、操作系统刷题笔记25 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;oracle…

Java实现栈结构

目录 一、栈概述 二、模拟实现栈 1、入栈 2、出栈 3、取栈顶元素 三、栈的应用 1、逆序打印链表 2、括号匹配问题 3、逆波兰表达式求值 4、栈的压入、弹出序列 5、最小栈 一、栈概述 栈&#xff08;Stack&#xff09;也是数据结构的一种&#xff0c;属于线性数…