目录
一、串口编程寄存器分析
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);
}