目录
前置学习
接口及引脚定义
注:VGA接口为15V,直接接到单片机上会损坏
学一下英语:
TXD:transmit exchange date 发射数据
RXD:receive external date 接收数据
常见的电平标准:
GND为0 V,都是相对于GND而言的
TTL 电平 | +5V表示1,0V表示0 | 在单片机中使用 |
RS235电平 | -3~-15V表示1,+3~+15V表示0 | 一般 用于电脑的数据传输,因其稳定性好,电压可容忍范围大 |
RS485电平 | 两线压差+2~+6V表示1,-2~-6V表示0(压差信号) | 两根线完成一根线的任务,极大提高传输距离 |
做数据流控制(流控),防止大量数据传输时,无法及时处理。
但51单片机不支持流控制
常见通信接口简介与UART(通用异步收发器)介绍
常见通信接口
点对点:只能两个设备间通信,一发多收
SCL SCLK为时钟线,故其为同步的
相关术语介绍:
全双工 | 可以同时接受传送数据 |
半双工 | 可相互传输数据,但分时使用一根数据线 |
单 工 | 只可单向发送数据,不可反向发送(接受) |
异步 | 通信双方各自约定通信速率 |
同步 | 通信双方靠一根时钟线来约定通信速率 |
总线 | (可挂载多设备的会有总线的说法) 连接各个设备的数据传输线路,每个设备挂在总线的两侧或由其延伸出去 |
UART介绍
只学模式一,所圈,即用到的两根线
如上的九位比八位多一位校验位
e.g.
奇检验:
检测位保证有奇数个1
传:0000 0011 1
接:0000 0011 1
0000 0101 1(这种无法校验出错误,排错率不高)
比特率(涉及调剂解调器的概念)、波特率:
都是表示传 送数据的快慢
圈起来的,小的那一部分是时钟模块
中断系统
由于在使用单片机接收信号时,要用到中断系统,因此,附上中断系统相关的知识
单片机有四个中断等级,但我(初学者)只用两个
串口与中断系统的联系
通过判断TI/(RI)是否等于1来确定是否发送/(接收)完成。发送完成,T1(RI)置1。
其中,IE即 Interrupt Enable,允许中断
串口中寄存器介绍,SCON以及PCON
简要介绍:
具体介绍:(来自单片机手册)
SBUF介绍:
SBUF即STC89C52系列的串行口缓冲寄存器,地址为99H,由两个寄存器共同占有该地址。
这两个寄存器一个只读,一个只写。有如下逻辑应用:
SBUF = a;
B = SBIUF;
具体说明附上截图
T1那个位置,产生波特率
应用
串口向电脑发送数据
由于我已将代码模块化,因此,将代码分段展示:
UART模块(接收时也会用到,故不会在下面再说明)
其中的中断部分是接收数据所用,此处不过多说明
#include <REGX52.H>
/* **
* @brief 串口初始化 //4800bps@11.0592MHz
* @param 无
* @retval 无
*/
void UART_Init(void) //4800bps@11.0592MHz
{
PCON |= 0x80; //使能波特率倍速位SMOD
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xF4; //设定定时初值
TH1 = 0xF4; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
EA = 1; //启动所有中断
ES = 1; //启动串口中断
}
/* * 串口发送模板
* @brief 串口发送一个字节数据
* @param Byte 要发送的一个数据
* @retval 无
*/
void UART_SendByte(unsigned char Byte)
{
SBUF = Byte;
while(TI == 0); //一执行完就要复位
TI = 0; //TI为发射控制器;RI为接受控制器;
}
/*串口中断函数模板
void UART_Routine() interrupt 4
{
if(RI = 1)
{
RI = 0;
}
}*/
main模块
//main
#include <REGX52.H>
#include "Delay.h"
#include "UART.H"
unsigned char sec;
void main()
{
UART_Init();
while(1)
{
UART_SendByte(sec);
sec++;
Delay(1000);
}
}
成果演示
串口控制LED(接收数据)
对中断部分的说明:
串口接收数据思路:
设置一个中断系统,当数据传入时,触发中断,在中断函数中进行数据处理
通过如下几个操作实现
打开接收开关,即REN = 1 。(处于SCON中)
EA = 1启动数据中断(EA是中断总开关)
ES = 1启动串口中断
TI 发送中断标志位
RI 接收中断标志位
中断完成后,必须用软件复位!
有四个中断优先级,不过我们是初学者只用两个(目前使用过1和现在的4):
若使用的是c语言,中断查询次序号就是中断号
函数名可以任写 interrupt跟到谁后面,谁就是中断子函数。
一个函数不能即在主函数中出现,又在中断函数中出现,这样会破坏主函数中的函数
如下是代码演示:
main模块
#include <REGX52.H>
#include "Delay.h"
#include "UART.H"
void main()
{
UART_Init();
while(1)
{
}
}
/*串口中断函数模板*/
void UART_Routine() interrupt 4
{
if(RI == 1)
{
P2 = ~SBUF;
UART_SendByte(SBUF);
RI = 0;
}
}
成果演示:
后言
STC-ISP配置
串口通信中,需要用到双8位自动重装(模式二)0~255
[CNT]->[AuroRelode]
给 1 0
因16位值0~65535且每次使用都要赋初值, 精度不高
勾选波特率加倍的原因:
在串口模式处要进行分频,不加倍会一直减速
在波特率计算器中遇到的问题
在写代码,使用STC—ISP计算波特率时,由于我所买的普中科技的单片机的晶振频率是11.0592MHZ,而在看视频时,(江科大)老师所用的是12.0000MHZ,导致我的晶振传递数据时,误差太大,在发送数据时,误差不是很明显,但在接收数据控制LED时,一直出现LED一场亮灭的情形,即数据一直无法正确传递。
解决方法:使用正确频率的波特率,软件配置以及代码如下:
已对代码进行删减,以配合我51的使用
/* **
* @brief 串口初始化 //4800bps@11.0592MHz
* @param 无
* @retval 无
*/
void UART_Init(void) //4800bps@11.0592MHz
{
PCON |= 0x80; //使能波特率倍速位SMOD
SCON = 0x50; //8位数据,可变波特率
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xF4; //设定定时初值
TH1 = 0xF4; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
EA = 1; //启动所有中断
ES = 1; //启动串口中断
}
波特率计算
波特率计算,以F3举例:
初始位置为0xF3 = 243
而数据每计数256(8位自动重装)溢出一次
即每计13个数,溢出一次
波特率为1/13微秒=0.07692MHZ 微秒等于兆赫兹
0.07692/ 16 =0.0048075MHZ = 4807.5HZ
数据显示模式
可位寻址和不可位寻址(瞎写的)
因为我忘了这个的概念,而且前面好像没有写。所以再次学习一下可位寻址和不可位寻址
一个寄存器可以储存一个字节的数据,也就是八个位。例如51单片机中的P1有八个接口,P1.0,P1.1等等,P1就是一个寄存器,他的每一个GPIO就对应了该寄存器字节的每一位。我们可以直接对P1赋值,如P1 = 0xFF 就代表p1.0-p.17全为高电平,也可以单独将某一位赋值,而只有在数据手册标注了可位寻址的寄存器才能够单独为某一位赋值。
可位寻址
既可以整体赋值,又可以单独赋值。
不可位寻址
而不可位寻址只能用0x00等整体赋值。