帧
UART 通信规范是以 8 位二进制数为一帧,低位在前,逐位的传输。
为了区分各个帧,在每一帧之前,要有一个 0 作为起始标记,之后,有一个 1,作为结束符。
在结束符之前,还可选发一个“校验位”,但是,目前多数的应用都不选择这个位。
那么,每次的串行通信,就是传送一个字节,加上前后的标记,共 10 位二进制数。
空闲时,发送的都是 1;一旦出现了 0,就说明开始传输数据了。
串行通信的一个重要指标就是传输速度,就是每秒传送了多少位二进制数。
这个速度称为波特率,单位是 bps,中文就是“位/秒”。
时间设定
当以 9600bps 来传送数据时,每一位数的持续时间是 (1/9600)s,这也就是间隔时间。
如果选用晶振频率是 11059200Hz,一个机器周期T的时间就是 (12/11059200)s
那么,一位数的持续时间 (1/9600)s,是多少个机器周期T呢 ?
这是很容易算的,就是下面的这个算式:
X = (1/9600) / (12/11059200) = 11059200 / 12 / 9600 = 96T
为了精确定时,可以利用定时器来定时,每当 96T 时间到了,就发送出去一位二进制数,这就行了。
实验程序
用 IO 口模拟串口输出的程序如下:
#include<reg52.h>
sbit TXD1 = P2^0//用IO口模拟串口发送端
sbit RXD1 = P2^1//用IO口模拟串口接收端
bit T96 //位变量
//----------------------------------------
void Wait96(void) //延时,控制波特率
{
while(T96) //等待出现0
T96 = 1 //清标志
}
//----------------------------------------
void WByte(char x)//发送一帧数据
{
char i
TL0 = 160 //初值=256-96=160
TXD1 = 0//发送起始位0
TR0 = 1 //启动定时器
Wait96()//等待96T
for (i = 0i <8i++) { //8位数
TXD1 = x &1 //先传低位
x >>= 1
Wait96() //等待96T
}
TXD1 = 1//发送结束位1
Wait96()//等待96T
TR0 = 0 //关闭定时器
}
//----------------------------------------
void main()
{
char i
TMOD = 0x02 //T0定时方式2
TH0 = 160 //初值=256-96=160
IE = 0x82
T96 = 1 //清标志
while(1) {
for (i = 0x41i <0x5bi++) //A~Z
WByte(i)
WByte(0x0D)
WByte(0x0A)
}
}
//----------------------------------------
void inttime0() interrupt 1 //T0中断
{
T96 = 0 //设置标志
}
//----------------------------------------
串口收发,要有通信协议。也就是什么时候开始接收,接收到指令后,转发什么数据。这个要知道,才可以写。而且使用不同的51单片机,其内部寄存器配置是不同的。一般来说,过程如下:
1,配置串口参数、波特率等,开启串口中断;
void Init_UART()
{
}
2,中断函数里写中断响应函数,根据接收的指令或者数据,执行相应的动作;
程序一般为:
void UART_ISR() interrupt x using y
{
串口中断处理函数
}
x - 单片机的C51中断号
y - 指定使用的当前工作寄存器组号(0-3 PSW中的RS0,RS1组合)
3,主程序
int main(void)
{
Init_UART()
while(1)
{
//数据发送函数
}
}
#include <reg51.h>
#include <intrins.h>
unsigned char key_s, key_v, tmp
char code str[] = "welcome! www.willar.com \n\r"
void send_str()
bit scan_key()
void proc_key()
void delayms(unsigned char ms)
void send_char(unsigned char txd)
sbit K1 = P1^4
main()
{
TMOD = 0x20// 定时器1工作于8位自动重载模式, 用于产生波特率
TH1 = 0xFD// 波特率9600
TL1 = 0xFD
SCON = 0x50// 设定串行口工作方式
PCON &= 0xef// 波特率不倍增
TR1 = 1// 启动定时器1
IE = 0x0// 禁止任何中断
while(1)
{
if(scan_key()) // 扫描按键
{
delayms(10)// 延时去抖动
if(scan_key()) // 再次扫描
{
key_v = key_s// 保存键值
proc_key()// 键处理
}
}
if(RI) // 是否有数据到来
{
RI = 0
tmp = SBUF// 暂存接收到的数据
P0 = tmp// 数据传送到P0口
send_char(tmp)// 回传接收到的数据
}
}
}
bit scan_key()
// 扫描按键
{
key_s = 0x00
key_s |= K1
return(key_s ^ key_v)
}
void proc_key()
// 键处理
{
if((key_v &0x01) == 0)
{ // K1按下
send_str()// 传送字串"welcome!...
}
}
void send_char(unsigned char txd)
// 传送一个字符
{
SBUF = txd
while(!TI)// 等特数据传送
TI = 0// 清除数据传送标志
}
void send_str()
// 传送字串
{
unsigned char i = 0
while(str[i] != '\0')
{
SBUF = str[i]
while(!TI)// 等特数据传送
TI = 0// 清除数据传送标志
i++// 下一个字符
}
}
void delayms(unsigned char ms)
// 延时子程序
{
unsigned char i
while(ms--)
{
for(i = 0i <120i++)
}
}
拓展资料
C语言是一门通用计算机编程语言,应用广泛。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台。
二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制定了一套完整的美国国家标准语法,称为ANSI C,作为C语言最初的标准。目前2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言的第三个官方标准,也是C语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)