-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSTC_Soft_uart_FullDuplex.lst
250 lines (239 loc) · 10.2 KB
/
STC_Soft_uart_FullDuplex.lst
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
C51 COMPILER V9.00 STC_SOFT_UART_FULLDUPLEX 05/19/2015 18:02:14 PAGE 1
C51 COMPILER V9.00, COMPILATION OF MODULE STC_SOFT_UART_FULLDUPLEX
OBJECT MODULE PLACED IN STC_Soft_uart_FullDuplex.obj
COMPILER INVOKED BY: g:\Keil\C51\BIN\C51.EXE Source\STC_Soft_uart_FullDuplex.c BROWSE INCDIR(..\电机控制) DEBUG OBJECTEX
-TEND PRINT(.\STC_Soft_uart_FullDuplex.lst) OBJECT(STC_Soft_uart_FullDuplex.obj)
line level source
1 /*
2 版权声明:
3 麦周老大(weibo.com/maizhoulaoda)版权所有(本程序在STC12系列上调试通过,收发都正常。)
4 基于赵学军先生在微计算机信息上的文章启示,修改一些错误并完善了该程序(修复bug例如recv中对停止位的处理等)�
-�
5 您可以任意修改本程序,并应用于任何项目。禁止收取任何软件费用。使用时请保留本段声明标明版权情况。
6 用定时器 T0 模拟全双工串行口程序。由麦周老大,Michael Zhou基于现有半双工STC软件串口程序修改
7 最高波特率(12 clock/3):
8 收、发波特率相同。
9
10 使用说明:
11 1. 本程序使用一个定时器(使用3倍波特率的定时)和任意 2 个 I/O 口模拟一个串行口(如果MCU主频够快,懂得编
-成,完全可以修改成模拟多个串口)。
12 2. 1位起始位,8位数据位,1位停止位。发数据位时先发低位。
13 3. 支持全双工通讯。收、发波特率相同。
14 4. 应把定时器中断优先级设置为最高级。
15 5. 本程序使用收,发两个环行缓冲区。使用者不必关心缓冲区的处理。如果接收缓冲满,则停止接收新的Rx输入,�
-钡接幸桓鲎纸诘目占浔惶诔觥�
16 **************************************************************************
17 编程说明:
18 ----------------
19 定时器0使用自动重装的8位计数器模式,保证波特率精度。
20 ----------------
21
22 发送:
23 调用 rs_send_byte () 启动发送一个字节的过程。
24 发送口平时为高电平,rs_send_byte ()函数使发送口变为低电平开始发送起始位;
25 同时设置和启动定时器,为发送数据位在预定的时刻产生定时器中断。发送数据位和停止位都在定时器的中断服务程序中
-进行。
26 ----------------
27 接收:
28 定时器以 3 倍波特率的频率产生中断检测Rx I/O管脚收到的起始位,准备在下一个定时器中断中接收第 1 个数据位
-。
29 中断服务程序中处理以下情况:
30 1. 收到的是起始位: 调整定时器产生中断的频率与波特率相同。
31 2. 收到第 8 位数据位: 存储接收到的字节。
32 3. 收到第 1--7 位数据位: 存储到收、发移位暂存器。
33 4. 收到停止位: 检测下一个起始位。
34 5. 处理出错的情况。
35 **************************************************************************
36
37 */
38 #include "STC_Soft_uart_FullDuplex.h"
39
40
41 INT8U Rbuf1[BufLong];//FIFO接收区
42 INT8U Rptr1,Rnum1;
43 INT8U Tbuf1[BufLong];//FIFO发送区
44 INT8U Tptr1,Tnum1;
45 signed char TimCnt1A,TimCnt1B;
46 INT8U Mtbuf1,Mrbuf1,TxdCnt1,RxdCnt1;
47 //INT8U RxdCnt2,Rnum2,Rptr2,Mrbuf2,Rbuf2[BufLong]; //如果需要两个9600 RxD,则添加这些变量。
48
49 INT16U ReceiveNextByteToRead,SendNextByteToWrite; //接收数据读取指针
C51 COMPILER V9.00 STC_SOFT_UART_FULLDUPLEX 05/19/2015 18:02:14 PAGE 2
50 bit Brxd1,Srxd1; //RxD检测电平
51 //INT16U ReceiveNextByteToRead2,SendNextByteToWrite2; //如果需要两个9600 RxD,则添加这些变量。
52 //bit Brxd2,Srxd2; //如果需要两个9600 RxD,则添加这些变量。
53
54 void Recv(void)
55 {
56 1
57 1
58 1 if(RxdCnt1>1) //存数据位8个
59 1
60 1 {
61 2
62 2 Mrbuf1>>=1;
63 2
64 2 if(RxD1==1) Mrbuf1=Mrbuf1|0x80;
65 2
66 2 }
67 1
68 1 RxdCnt1--;
69 1
70 1 if(RxdCnt1==1 /*&& RxD1==1*/) //数据接收完毕,未接收停止位。 RxdCnt1==0时,接收停止位
71 1
72 1 {
73 2 Brxd1=Srxd1=1; //重置接收状态等待下一个起始位。
74 2 if(Rnum1<BufLong) //FIFO队列未满
75 2 {
76 3 Rbuf1[Rptr1]=Mrbuf1; //存储到FIFO队列
77 3 if(++Rptr1>BufLong-1) Rptr1=0;
78 3 if(++Rnum1>BufLong) Rnum1=BufLong; //FIFO队列已满,不再允许数据添加
79 3 }
80 2
81 2 }
82 1
83 1 }
84
85 void Send(void)
86 {
87 1
88 1 if(TxdCnt1!=0) //字节发送状态机
89 1
90 1 {
91 2
92 2 if(TxdCnt1==11) TxD1=0;//发起始位0
93 2
94 2 else if(TxdCnt1>2) //发数据位
95 2
96 2 { Mtbuf1>>=1; TxD1=CY;}
97 2
98 2 else TxD1=1; //发终止位1
99 2
100 2 TxdCnt1--;
101 2
102 2 }
103 1
104 1 else if(Tnum1>0) //检测FIFO队列
105 1
106 1 {
107 2
108 2 Tnum1--;
109 2
110 2 Mtbuf1=Tbuf1[Tptr1]; //读取FIFO数据
111 2
C51 COMPILER V9.00 STC_SOFT_UART_FULLDUPLEX 05/19/2015 18:02:14 PAGE 3
112 2 if(++Tptr1>=BufLong) Tptr1=0;
113 2
114 2 TxdCnt1=11; //启动发送状态机
115 2
116 2 }
117 1
118 1 }
119
120
121 #ifdef TIMER_0
122 void timer0 (void) interrupt 1 using 3
123 {
124 1 if(RxdCnt1==0 ) //接收起始识别
125 1
126 1 {
127 2 if(RxD1==0 && Brxd1==0 && Srxd1==1) { RxdCnt1=9; TimCnt1B=0;} //第一个数据位间隔取4,保证读取脉冲中间
128 2 Srxd1=Brxd1; Brxd1=RxD1;
129 2 }
130 1
131 1
132 1 if(++TimCnt1B>=3 && RxdCnt1!=0) {TimCnt1B=0; Recv();}//数据接收,间隔为3
133 1
134 1 if(++TimCnt1A>=3) { TimCnt1A=0; Send();} //数据发送
135 1 }
136 #endif
137
138
139
140 void soft_rs232_init (void) //串口初始化
141 {
142 1 TH0=-BaudT; TL0=-BaudT; TR0=1;
143 1
144 1 Rptr1=0;Rnum1=0;Tptr1=0;Tnum1=0;
145 1
146 1 RxdCnt1=TxdCnt1=0;
147 1
148 1
149 1 AUXR |= 0x00; //Set T0x12 = 0, 12分频
150 1
151 1 TMOD &= TMOD_AND_WORD;
152 1 TMOD |= TMOD_TIME_MODE2; //模式2,溢出触发中断后硬件自动将THx重装入TLx 确保定时器精度
153 1 Brxd1=Srxd1=RxD1 = 1; //接收脚置成高电平
154 1 TxD1 = 1; //发射脚置成高电平
155 1
156 1 ReceiveNextByteToRead=SendNextByteToWrite=0; //接收环形缓冲读取/写入指针初始化
157 1 IP_PTx = 1; //置中断优先级为高
158 1 EA=1; //开启总中断
159 1 IE_ETx = 1; //允许定时器中断
160 1 IE|=0x82;
161 1 TCON_ENABLE_TIMER = 1; //启动定时器
162 1 }
163
164 void initiate_soft_uart (void) //软件串口初始化
165 {
166 1 soft_rs232_init(); //串口初始化
167 1 EA = 1; //开中断
168 1 }
169
170
171 //由收转到发时,要先调用 soft_send_enable ()
172 void rs_send_byte(INT8U SendByte) //发送一个字节
173 {
C51 COMPILER V9.00 STC_SOFT_UART_FULLDUPLEX 05/19/2015 18:02:14 PAGE 4
174 1 while ( Tnum1 >= BufLong); //等待FIFO队列有空
175 1 Tbuf1[SendNextByteToWrite]=SendByte;
176 1 if(++SendNextByteToWrite>BufLong-1) SendNextByteToWrite=0;
177 1 if(++Tnum1>BufLong) Tnum1=BufLong; //FIFO队列已满,不再允许数据添加
178 1 }
179
180 INT8U rs_receive_byte(void) //接收一个字节 先调用soft_receive_enable()
181 {
182 1 INT8U outputByte=0;
183 1
184 1 while(Rnum1==0); //等待接收到一个字符
185 1
186 1 outputByte=Rbuf1[ReceiveNextByteToRead];
187 1 if( ReceiveNextByteToRead<BufLong-1)
188 1 {
189 2 ReceiveNextByteToRead++;
190 2 }else{
191 2 ReceiveNextByteToRead=0;
192 2 }
193 1 Rnum1--; //读取完毕,从FIFO队列中腾出一个字符
194 1
195 1 return outputByte;
196 1
197 1 }
198
199 /* 测试用main函数例子*/
200 void main (void)
201 {
202 1 //当收到 1个字节后,立刻将收到的数据回发送给 PC 机,然后继续等待下一个数据字节。
203 1
204 1 INT8U ReceivedData;
205 1 initiate_soft_uart(); //初始化
206 1
207 1 while(1)
208 1 {
209 2 ReceivedData=rs_receive_byte();
210 2 rs_send_byte(ReceivedData);
211 2
212 2 }
213 1 }
214
215
MODULE INFORMATION: STATIC OVERLAYABLE
CODE SIZE = 373 ----
CONSTANT SIZE = ---- ----
XDATA SIZE = ---- ----
PDATA SIZE = ---- ----
DATA SIZE = 78 ----
IDATA SIZE = ---- ----
BIT SIZE = 2 ----
END OF MODULE INFORMATION.
C51 COMPILATION COMPLETE. 0 WARNING(S), 0 ERROR(S)