差分信号
即通过两根线的电压差与地线比较。
术语解释
由于我们使用的是USB接口,单片机还有一个USB转串口电路,如下
串口参数及时序图
总的连接线路如图:
串口的相关寄存器
寄存器详情(来源于官方文档)
我这里使用的是11.0592MHz的晶振频率,借助stc配置波特率,然后再让电脑波特率与其一致(异步通信)
然后根据自己的需求完善,完整的串口初始化代码(UART_Init.c)如下:
#include <REGX52.H>
// 初始化串口
void UART_Init(){
// 配置SCON寄存器
/*
SM0/FE 0,不需要帧错误检测
SM0 SM1组合确定串口工作方式,使用方式1,给1,
8位UART,波特率为(2^SMOD/32)*(定时器1的溢出率),
<(定时器1的溢出率)12T为SYSclk/12/(256-TH1),6T为SYSclk/6/(256-TH1)>>
SM2 用于方式2、3,给0
REN 允许/进制串行接收控制位,由软件置位、复位,给0
TB8 用于方式2、3,给0
RB8 用于方式2、3,给0
TI 发送中断请求,开始由内部硬件置位,由软件复位,给0
*/
SCON = 0X40; // 0100 0000
// 配置电源控制寄存器PCON
/*
SMOD 波特率选择,为1是方式1、2、3波特率加倍,为0全部方式加倍
SMOD0 帧错误检查,目前不需要,给0
*/
PCON |= 0x80;
// 暂时不需要使用中断,不用配置其他的寄存器
// 配置定时器1,串口使用的是8位自动重载
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xF4; //设置定时初始值
TH1 = 0xF4; //设置定时重载值
TR1 = 1; //定时器0开始计时
ET1 = 0; // 禁止TF0的中断请求
}
以上面代码配置为例解释波特率的计算过程
使用的是8位自动重载,赋值为0xf4,即244,每个盒子为8位,即256,所以每256-244 = 12um溢出一次,所以此时的溢出率为11.0592/12/12 = 0.0768,然后0.0768/16= 0.0048MHz,即4800Hz
数据首先要发送到串口的缓冲区,然后才会发送,将函数封装于主函数中,主函数(main.c)如下:
#include <REGX52.H>
#include "Delay.h"
#include "UART_Init.h"
// 发送数据
void UART_sendByte(unsigned char byte){
SBUF = byte; // 将数据写入串口缓冲区
while(TI == 0); // 数据发出去即跳出循环
TI = 0; // 需手动复位
}
unsigned char count = 0;
void main(){
UART_Init();
// 每隔1s发送递增数据
while(1){
UART_sendByte(count);
count++;
Delayms(1000);
}
}
点击USB-CDC/串口助手,配置正确后打开串口,即可接收数据,如果选择的是文本模式,会通过ASCII码编码后显示
由于电脑发送数据没有固定时间,所以需要使用中断来接收数据,需要对初始化函数进行更新,UART_Init.c如下:
#include <REGX52.H>
// 初始化串口
void UART_Init(){
// 配置SCON寄存器
// 使用方式1,允许中断
SCON = 0X50; // 0101 0000
// 配置电源控制寄存器PCON
/*
SMOD 波特率选择,为1是方式1、2、3波特率加倍,为0全部方式加倍
SMOD0 帧错误检查,目前不需要,给0
*/
PCON |= 0x80;
// 暂时不需要使用中断,不用配置其他的寄存器
// 配置定时器1,串口使用的是8位自动重载
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xF4; //设置定时初始值
TH1 = 0xF4; //设置定时重载值
TR1 = 1; //定时器0开始计时
ET1 = 1; // 允许TF0的中断请求
EA = 1; // 打开中断
ES = 1; // 打开中断总开关
}
main.c配置如下:
#include <REGX52.H>
#include "Delay.h"
#include "UART_Init.h"
// 发送数据
void UART_sendByte(unsigned char byte){
SBUF = byte; // 将数据写入串口缓冲区
while(TI == 0); // 数据发出去即跳出循环
TI = 0; // 需手动复位
}
void main(){
UART_Init();
while(1){
}
}
// 配置中断函数
void UART_Routine() interrupt 4
{
// 只要RI>=1(收)或者TI>=1(发)就会触发串口中断。前提是程序打开了总中断和串口中断。
// 串口接收数据后,硬件会自动将RI置1
if(RI == 1){
P2 = SBUF; // 从缓冲区读取数据
UART_sendByte(SBUF); // 发回数据
RI = 0;
}
}
验证结果