转:STC15F系列单片机模拟串口57600bps@24MHz

1 // 为何不把程序写得通俗易懂点?超级代码来了!
2 // 参考了 STC 官网手册中的程序,但源程序遇到 RX 脚一直为低电平也会收到数据 0x00, 这里已经修正
3 // 柳州市第一职业技术学校 电气自动化专业部 中国欧软 China O Soft! 2012 年 8 月 3 日
4 #include <reg52.h> // 使用 8052 内核单片机
5 sbit TX_IO=P3^1; // 模拟串口发送 IO
6 sbit RX_IO=P3^0; // 模拟串口接收 IO
7 sfr AUXR=0x8e; //STC15F 系列单片机特殊寄存器 , 控制定时器时钟来源频率
8 bit sending,receing,received; // 发送中 , 接收中 , 接收完毕标志
9 unsigned char rece_bit_count; // 接收位计数变量
10 unsigned char rece_pls_count; // 接收脉冲计数变量
11 unsigned char send_bit_count; // 发送位计数变量
12 unsigned char send_pls_count; // 发送脉冲计数变量
13 unsigned char receing_data; // 正在接收着的临时数据
14 unsigned char byte_need_to_send; // 要发送出去的字节
15 unsigned char byte_received; // 已收到的字节
16
17 void send_byte(unsigned char byte_will_send) // 发送一个字节
18 { // 函数开始
19 byte_need_to_send=byte_will_send; // 传递要发送的数据
20 send_pls_count=3; // 采样倍率 3
21 send_bit_count=8; //8 位数据一位停止
22 TX_IO=0; // 发送起始位
23 sending=1; // 置标志位,中断程序开始发送该字节
24 while(sending); // 等待数据发送完成
25 } // 函数结束
26
27 void timer0(void) interrupt 1 // 中断服务程序
28 { // 函数开始
29 if(receing) // 接收中 ?
30 { // 接收中开始
31 if(--rece_pls_count==0) // 三次脉冲计数够了吗 ?
32 { // 接收一位二进制位开始
33 rece_pls_count=3; // 脉冲计数辅助变量复位
34 if(rece_bit_count) // 是在接收数据位还是停止位
35 { // 接收数据位开始
36 receing_data=receing_data>>1; // 向右移一位 , 准备拼入一位二进制数据
37 if(RX_IO==1){receing_data=receing_data|0x80;}// 如果收到的是二进制位 "1", 则拼入最高位中
38 rece_bit_count=rece_bit_count-1; // 已接收一位 , 接收位计数变量计数
39 } // 接收数据位结束
40 else // 如果已经收完 8 位数据
41 { // 就开始接收停止位
42 receing=0; // 本字节已接收完毕
43 if(RX_IO==1) // 停止位是 "1" 吗
44 { // 是 “1”
45 byte_received=receing_data; // 将数据输出
46 received=1; // 摇旗示意数据正确接收完毕
47 } // 数据输出处理完毕
48 } // 停止位处理完毕
49 } // 接收一位二进制位结束
50 } // 接收中处理结束
51 else // 还没收到停止位 , 不是正在接收状态
52 { // 等待接收开始
53 if(RX_IO==0) // 是一个起始位到来吗
54 { // 是 .......
55 receing=1; // 开始接收
56 rece_pls_count=3; // 置接收起始位脉冲数
57 rece_bit_count=8; // 置接收二进制位数
58 } // 起始位处理完毕
59 } // 等待接收完毕
60 //----------------------------------------------------------------------------------------
61 if(sending) // 是正在发送状态吗
62 { // 是 ……
63 if(--send_pls_count==0) // 脉冲计数够了吗
64 { // 够了 ……
65 send_pls_count=3; // 脉冲计数复位
66 if(send_bit_count) // 是在发送数据还是要发送停止位
67 { // 发送数据开始
68 TX_IO=byte_need_to_send&0x01; // 从最低位开始发送数据
69 byte_need_to_send=byte_need_to_send>>1; // 移动数据准备下一次发送
70 send_bit_count=send_bit_count-1; // 已经发送了一位二进制数要记下来
71 } // 发送数据结束
72 else // 数据已经发送完成
73 { // 发送停止位开始
74 TX_IO=1; // 发送停止位
F:\ 中国欧软 STC15F 系列单片机模拟串口 57600bps@24MHz.c
Page 2
75 sending=0; // 放下旗帜表示数据已经发送完成
76 } // 停止位发送完成
77 } // 一位二进制位处理完成
78 } // 发送状态处理完成
79 } // 中断函数结束
80 void main(void) // 主程序
81 { // 开始
82 AUXR=0x80; //T0 计时脉冲不分频,比传统 8051 快 12 倍
83 TMOD=0X00; //16 位自动重载模式,当 TR0=0 时向 TH0,TL0 写入数据将同时写入重载寄存器
84 TH0=(65536-(24000000/57600/3))/256; // 重载值 =65536- (定时器脉冲频率 ÷ 波特率 ÷3 )
85 TL0=(65536-(24000000/57600/3))%256; // 溢出率 = 定时器脉冲频率 ÷ ( 65536- 重载值)
86 TR0=1; // 启动定时器 , 模拟串口开始工作
87 EA=1; // 打开总中断
88 ET0=1; // 打开定时器 0 中断
89 PX0=1; // 优先保证定时器 0 中断,确保模拟串口的可靠性
90 while(1) // 主循环
91 { // 主循环体开始
92 if(received==1) // 收到一个字节的数据啦 ?
93 { // 是 ……
94 received=0; // 知道了 ……
95 send_byte(byte_received); // 原封不动打回原籍
96 } // 收到字节处理完毕
97 } // 主循环体结束
98 } 

 原文地址:https://www.amobbs.com/thread-5489990-1-1.html

posted @ 2018-01-01 00:05  XZHDJH  阅读(445)  评论(0)    收藏  举报