文章目录
- 日常·唠嗑:
- 一、什么是Lora模块
- 二、通讯方式是什么
- 1、模块选择
- 2、参数及设置
- 3、接线方式
- 1、通信接线
- 2、参数修改接线
- 三、Robei程序设计
- 总结
日常·唠嗑:
今年华南赛区结束了,还有二十多天才进行国赛,也算是有几天清闲日子。对于Lora,我有着特殊的情感,从上届集创赛我就一直用到现在。起初我一直执着于WiFi模块,但是WiFi模块对FPGA小白程序员是一点都不友好,然后俩零同学就给我推荐了这款无线扩频模块。随着LoRa技术的不断成熟,现在LoRa已经在国内外得到广泛应用,在这个领域中的人对LoRa并不陌生。LoRa是一种专用于远距离低功耗的无线通信技术,其调制方式相对于其他通信方式大大增加了通信距离,可广泛应用于各种场合的远距离低速率物联网无线通信领域。下面就简单说说如何在Robei中设计Lora与机器人通讯。
一、什么是Lora模块
要了解LoRa模块就要先了解LoRa,LoRa是低功耗广域网通信技术中的一种,是Semtech公司采用和推广的一种基于扩频技术的超远距离无线传输技术,是Semtech 射频部分产生的一种独特的调制格式。LoRa模块就是基于Semtech公司SX1276/1278芯片研发的无线数传模块,这种芯片集成规模小、效率高,从而让LoRa模块拥有高接收灵敏度。
LoRa的优势主要体现在以下几个方面:
1、大大的改善了接收的灵敏度,降低了功耗。
高达157db的链路预算使其通信距离可达15公里(与环境有关)。其接收电流仅10mA,睡眠电流200nA,这大大延迟了电池的使用寿命。
2、基于该技术的网关/集中器支持多信道多数据速率的并行处理,系统容量大。
网关是节点与IP网络之间的桥梁(通过2G/3G/4G或者Ethernet)。每个网关每天可以处理500万次各节点之间的通信(假设每次发送10Bytes,网络占用率10%)。如果把网关安装在现有移动通信基站的位置,发射功率20dBm(100mW),那么在建筑密集的城市环境可以覆盖2公里左右,而在密度较低的郊区,覆盖范围可达10公里。
3、基于终端和集中器/网关的系统可以支持测距和定位。
LoRa对距离的测量是基于信号的空中传输时间而非传统的RSSI(Received Signal Sterngth Ind-ication),而定位则基于多点(网关)对一点(节点)的空中传输时间差的测量。其定位精度可达5m(假设10km的范围)。
4、高保密性、高隐蔽性
采用LoRa调制方式,传统无线设备无法对其进行获、解析,带内平均功率低于底噪时仍然可以正常通讯。
二、通讯方式是什么
1、模块选择
某宝的lora模块有很多种,选择哪种模块呢?
建议选择亿佰特,他们家是专门做lora模块的,有各种型号,价格也很便宜,模块加天线,两套才31RMB。而且他们家的模块,写起程序来要比其他的方便很多,想正点原子的lora模块就很麻烦,进行通讯还要配置各种环境。用亿佰特的,只要以UART协议 进行程序编写就行了。
2、参数及设置
我选择的是,E32-433T20DC LoRa扩频 ,一下是他的参数:
芯片方案:SX1278
载波频率:410~441MHz
发射功率:10~20dBm
通信距离:3km
通信接口:UART
默认波特率:9600
产品净量:6.3±0.1g
产品简介:其嵌入高速低功耗单片机和高性能LoRa扩频芯片SX1278,采用高效的循环交织纠检错编码,抗干扰和灵敏度都大大提高。发射功率100mW,低功耗,具有无线唤醒功能,LoRa扩频能够带来更远的通讯距离。
这里提一下,他的波特率是默认9600的,你可以在他们官网下载APP修改波特率以及其他参数。
3、接线方式
1、通信接线
从下图可以看到,模块有7个排针,1-7号,M1,M2主要是选择工作模式,一般通信模式需要将这两个引脚接地(可以拿面包板将这两个引脚跟7引脚GND接在一起),3是RXD接开发板的TXD,4是TXD开发板RXD;5引脚不用理,悬空就好;6是VCC,接电源3.3V-5V。
这里我觉得接面包板线太多,又乱,就画了快简单的扩展板:
有了扩展板,这样就很方便了,就像普通的串口通讯一样。
2、参数修改接线
上面说到,可以通过官网的软件修改模块波特率,修改参数的话,主要是在上一小节的基础上,将M1,M2置高电平, 也就是拉高。下面看一下模块的工作选择表;接线完,直接通过CH340模块接到电脑,打开APP读取参数,修改,保存就好了。
三、Robei程序设计
1、首先构建顶层,打开Robei EDA,new一个module:robei_lora
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
46module robei_lora( sys_clk, sys_rst_n, uart_rxd, uart_txd); //----Parameters:: generated by Robei----- parameter CLK_FREQ = 50000000; parameter UART_BPS = 9600; //---Ports declearation: generated by Robei--- input sys_clk; input sys_rst_n; input uart_rxd; output uart_txd; wire sys_clk; wire sys_rst_n; wire uart_rxd; wire uart_txd; //----Code starts here: integrated by Robei----- wire uart_en_w; //UART发送使能 wire [7:0] uart_data_w; //UART发送数据 wire clk_1m_w; //1MHz时钟,用于Signaltap调试 //---Module instantiation--- lora_send #( 50000000, 9600) lora_send1( .sys_clk(sys_clk), .sys_rst_n(sys_rst_n), .uart_en(uart_en_w), .uart_din(uart_data_w), .uart_txd(uart_txd)); lora_recv #( 50000000, 9600) lora_recv2( .sys_clk(sys_clk), .sys_rst_n(sys_rst_n), .uart_rxd(uart_rxd), .uart_done(uart_en_w), .uart_data(uart_data_w)); endmodule //robei_lora
2、写一个接收模块:lora_recv
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
133module lora_recv( sys_clk, sys_rst_n, uart_rxd, uart_done, uart_data); //----Parameters:: generated by Robei----- parameter CLK_FREQ = 50000000; parameter UART_BPS = 9600; //---Ports declearation: generated by Robei--- input sys_clk; input sys_rst_n; input uart_rxd; output uart_done; output [7:0] uart_data; wire sys_clk; wire sys_rst_n; wire uart_rxd; reg uart_done; reg [7:0] uart_data; //----Code starts here: integrated by Robei----- localparam BPS_CNT = CLK_FREQ/UART_BPS; //为得到指定波特率, //需要对系统时钟计数BPS_CNT次 //reg define reg uart_rxd_d0; reg uart_rxd_d1; reg [15:0] clk_cnt; //系统时钟计数器 reg [ 3:0] rx_cnt; //接收数据计数器 reg rx_flag; //接收过程标志信号 reg [ 7:0] rxdata; //接收数据寄存器 //wire define wire start_flag; //捕获接收端口下降沿(起始位),得到一个时钟周期的脉冲信号 assign start_flag = uart_rxd_d1 & (~uart_rxd_d0); //对UART接收端口的数据延迟两个时钟周期 always @(posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) begin uart_rxd_d0 <= 1'b0; uart_rxd_d1 <= 1'b0; end else begin uart_rxd_d0 <= uart_rxd; uart_rxd_d1 <= uart_rxd_d0; end end //当脉冲信号start_flag到达时,进入接收过程 always @(posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) rx_flag <= 1'b0; else begin if(start_flag) //检测到起始位 rx_flag <= 1'b1; //进入接收过程,标志位rx_flag拉高 else if((rx_cnt == 4'd9)&&(clk_cnt == BPS_CNT/2)) rx_flag <= 1'b0; //计数到停止位中间时,停止接收过程 else rx_flag <= rx_flag; end end //进入接收过程后,启动系统时钟计数器与接收数据计数器 always @(posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) begin clk_cnt <= 16'd0; rx_cnt <= 4'd0; end else if ( rx_flag ) begin //处于接收过程 if (clk_cnt < BPS_CNT - 1) begin clk_cnt <= clk_cnt + 1'b1; rx_cnt <= rx_cnt; end else begin clk_cnt <= 16'd0; //对系统时钟计数达一个波特率周期后清零 rx_cnt <= rx_cnt + 1'b1; //此时接收数据计数器加1 end end else begin //接收过程结束,计数器清零 clk_cnt <= 16'd0; rx_cnt <= 4'd0; end end //根据接收数据计数器来寄存uart接收端口数据 always @(posedge sys_clk or negedge sys_rst_n) begin if ( !sys_rst_n) rxdata <= 8'd0; else if(rx_flag) //系统处于接收过程 if (clk_cnt == BPS_CNT/2) begin //判断系统时钟计数器计数到数据位中间 case ( rx_cnt ) 4'd1 : rxdata[0] <= uart_rxd_d1; //寄存数据位最低位 4'd2 : rxdata[1] <= uart_rxd_d1; 4'd3 : rxdata[2] <= uart_rxd_d1; 4'd4 : rxdata[3] <= uart_rxd_d1; 4'd5 : rxdata[4] <= uart_rxd_d1; 4'd6 : rxdata[5] <= uart_rxd_d1; 4'd7 : rxdata[6] <= uart_rxd_d1; 4'd8 : rxdata[7] <= uart_rxd_d1; //寄存数据位最高位 default:; endcase end else rxdata <= rxdata; else rxdata <= 8'd0; end //数据接收完毕后给出标志信号并寄存输出接收到的数据 always @(posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) begin uart_data <= 8'd0; uart_done <= 1'b0; end else if(rx_cnt == 4'd9) begin //接收数据计数器计数到停止位时 uart_data <= rxdata; //寄存输出接收到的数据 uart_done <= 1'b1; //并将接收完成标志位拉高 end else begin uart_data <= 8'd0; uart_done <= 1'b0; end end endmodule //lora_recv
3、写一个发送模块:lora_send
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
124module lora_send( sys_clk, sys_rst_n, uart_en, uart_din, uart_txd); //----Parameters:: generated by Robei----- parameter CLK_FREQ = 50000000; parameter UART_BPS = 9600; //---Ports declearation: generated by Robei--- input sys_clk; input sys_rst_n; input uart_en; input [7:0] uart_din; output uart_txd; wire sys_clk; wire sys_rst_n; wire uart_en; wire [7:0] uart_din; reg uart_txd; //----Code starts here: integrated by Robei----- localparam BPS_CNT = CLK_FREQ/UART_BPS; //为得到指定波特率,对系统时钟计数BPS_CNT次 //reg define reg uart_en_d0; reg uart_en_d1; reg [15:0] clk_cnt; //系统时钟计数器 reg [ 3:0] tx_cnt; //发送数据计数器 reg tx_flag; //发送过程标志信号 reg [ 7:0] tx_data; //寄存发送数据 //wire define wire en_flag; //捕获uart_en上升沿,得到一个时钟周期的脉冲信号 assign en_flag = (~uart_en_d1) & uart_en_d0; //对发送使能信号uart_en延迟两个时钟周期 always @(posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) begin uart_en_d0 <= 1'b0; uart_en_d1 <= 1'b0; end else begin uart_en_d0 <= uart_en; uart_en_d1 <= uart_en_d0; end end //当脉冲信号en_flag到达时,寄存待发送的数据,并进入发送过程 always @(posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) begin tx_flag <= 1'b0; tx_data <= 8'd0; end else if (en_flag) begin //检测到发送使能上升沿 tx_flag <= 1'b1; //进入发送过程,标志位tx_flag拉高 tx_data <= uart_din; //寄存待发送的数据 end else if ((tx_cnt == 4'd9)&&(clk_cnt == BPS_CNT/2)) begin //计数到停止位中间时,停止发送过程 tx_flag <= 1'b0; //发送过程结束,标志位tx_flag拉低 tx_data <= 8'd0; end else begin tx_flag <= tx_flag; tx_data <= tx_data; end end //进入发送过程后,启动系统时钟计数器与发送数据计数器 always @(posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) begin clk_cnt <= 16'd0; tx_cnt <= 4'd0; end else if (tx_flag) begin //处于发送过程 if (clk_cnt < BPS_CNT - 1) begin clk_cnt <= clk_cnt + 1'b1; tx_cnt <= tx_cnt; end else begin clk_cnt <= 16'd0; //对系统时钟计数达一个波特率周期后清零 tx_cnt <= tx_cnt + 1'b1; //此时发送数据计数器加1 end end else begin //发送过程结束 clk_cnt <= 16'd0; tx_cnt <= 4'd0; end end //根据发送数据计数器来给uart发送端口赋值 always @(posedge sys_clk or negedge sys_rst_n) begin if (!sys_rst_n) uart_txd <= 1'b1; else if (tx_flag) case(tx_cnt) 4'd0: uart_txd <= 1'b0; //起始位 4'd1: uart_txd <= tx_data[0]; //数据位最低位 4'd2: uart_txd <= tx_data[1]; 4'd3: uart_txd <= tx_data[2]; 4'd4: uart_txd <= tx_data[3]; 4'd5: uart_txd <= tx_data[4]; 4'd6: uart_txd <= tx_data[5]; 4'd7: uart_txd <= tx_data[6]; 4'd8: uart_txd <= tx_data[7]; //数据位最高位 4'd9: uart_txd <= 1'b1; //停止位 default: ; endcase else uart_txd <= 1'b1; //空闲时发送端口为高电平 end endmodule //lora_send
4、将这两个子模块加进顶层模块连线就行了。
5、实物图
下位机:
上位机:
通过接线后就可以实现上位机与下位机回环通信。
也许有同学需要用到的是,下位机发送指定指令给上位机,比如人体检测模块检测到人的时候向上位机发送发现人员,这里一并满足大家。
按下按键后,开发板通过Lora向上位机发送:Fa Xian,需要其他指令的同学可以自己修改。
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
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316module UART(clk, rst, rxd, txd, en, seg_data, key_input, lowbit); input clk,rst; input rxd; //串行数据接收端 input key_input; //按键输入 output[7:0] en /*synthesis keep*/ ; output[7:0] seg_data; reg[7:0] seg_data; output txd; //串行数据发送端 output lowbit; //***************************inner reg*******************************// reg[15:0] div_reg; //分频计数器,分频值由波特率决定。分频后得到频率8倍波特率的时钟 reg[2:0] div8_tras_reg; //该寄存器的计数值对应发送时当前位于的时隙数 reg[2:0] div8_rec_reg; //该寄存器的计数值对应接收时当前位于的时隙数 reg[3:0] state_tras; //发送状态寄存器 reg[3:0] state_rec; //接受状态寄存器 reg clkbaud_tras; //以波特率为频率的发送使能信号 reg clkbaud_rec; //以波特率为频率的接受使能信号 reg clkbaud8x; //以8倍波特率为频率的时钟,它的作用是将发送或接受一个bit的时钟周期分为8个时隙 reg recstart; //开始发送标志 reg recstart_tmp; reg trasstart; //开始接受标志 reg rxd_reg1; //接收寄存器1 reg rxd_reg2; //接收寄存器2,因为接收数据为异步信号,故用两级缓存 reg txd_reg; //发送寄存器 reg[7:0] rxd_buf /*synthesis keep*/ ; //接受数据缓存 reg[7:0] txd_buf /*synthesis keep*/ ; //发送数据缓存 reg[2:0] send_state /*synthesis keep*/ ; //每次按键给PC发送"Welcome"字符串,这是发送状态寄存器 reg[19:0] cnt_delay; //延时去抖计数器 reg start_delaycnt; //开始延时计数标志 reg key_entry1, key_entry2;//确定有键按下标志 parameter div_par = 16'h145; //分频参数,其值由对应的波特率计算而得,按此参数分频的时钟频率是波倍特率的8 //倍,此处值对应9600的波特率,即分频出的时钟频率是9600*8 (CLK 50M) //**********************************************************// assign txd = txd_reg; assign lowbit = 0; assign en = 0; //7段数码管使能信号赋值 //**********************************************************// always@(posedge clk) begin if(!rst) begin cnt_delay <= 0; start_delaycnt <= 0; end else if(start_delaycnt) begin if(cnt_delay != 20'd800000) begin cnt_delay <= cnt_delay + 1;end else begin cnt_delay <= 0; start_delaycnt <= 0; end end else begin if(!key_input && cnt_delay == 0) start_delaycnt <= 1; end end //**********************************************************// always@(posedge clk) begin if(!rst) key_entry1 <= 0; else begin if(key_entry2) key_entry1 <= 0; else if(cnt_delay == 20'd800000) begin if(!key_input) key_entry1 <= 1; end end end //**********************************************************// always@(posedge clk) begin if(!rst) div_reg <= 0; else begin if(div_reg == div_par - 1) div_reg <= 0; else div_reg <= div_reg + 1; end end //**********************************************************// always@(posedge clk) //分频得到8倍波特率的时钟 begin if(!rst) clkbaud8x <= 0; else if(div_reg == div_par - 1) clkbaud8x <= ~clkbaud8x; end //**********************************************************// always@(posedge clkbaud8x or negedge rst) begin if(!rst) div8_rec_reg <= 0; else if(recstart) //接收开始标志 div8_rec_reg <= div8_rec_reg + 1; //接收开始后,时隙数在8倍波特率的时钟下加1循环 end //**********************************************************// always@(posedge clkbaud8x or negedge rst) begin if(!rst) div8_tras_reg <= 0; else if(trasstart) div8_tras_reg <= div8_tras_reg + 1; //发送开始后,时隙数在8倍波特率的时钟下加1循环 end //**********************************************************// always@(div8_rec_reg) begin if(div8_rec_reg == 7) clkbaud_rec = 1; //在第7个时隙,接收使能信号有效,将数据打入 else clkbaud_rec = 0; end //**********************************************************// always@(div8_tras_reg) begin if(div8_tras_reg == 7) clkbaud_tras = 1; //在第7个时隙,发送使能信号有效,将数据发出 else clkbaud_tras = 0; end //**********************************************************// always@(posedge clkbaud8x or negedge rst) begin if(!rst) begin txd_reg <= 1; trasstart <= 0; txd_buf <= 0; state_tras <= 0; send_state <= 0; key_entry2 <= 0; end else begin if(!key_entry2) begin if(key_entry1) begin key_entry2 <= 1; txd_buf <= 8'd70; end end//"F" else begin case(state_tras) 4'b0000: begin //发送起始位 if(!trasstart && send_state < 7) trasstart <= 1; else if(send_state < 7) begin if(clkbaud_tras) begin txd_reg <= 0; state_tras <= state_tras + 1;end end else begin key_entry2 <= 0; state_tras <= 0; end end 4'b0001: begin //发送第1位 if(clkbaud_tras) begin txd_reg <= txd_buf[0]; txd_buf[6:0] <= txd_buf[7:1]; state_tras <= state_tras + 1; end end 4'b0010: begin //发送第2位 if(clkbaud_tras) begin txd_reg <= txd_buf[0]; txd_buf[6:0] <= txd_buf[7:1]; state_tras <= state_tras + 1; end end 4'b0011: begin //发送第3位 if(clkbaud_tras) begin txd_reg <= txd_buf[0]; txd_buf[6:0] <= txd_buf[7:1]; state_tras <= state_tras + 1; end end 4'b0100: begin //发送第4位 if(clkbaud_tras) begin txd_reg <= txd_buf[0]; txd_buf[6:0] <= txd_buf[7:1]; state_tras <= state_tras + 1; end end 4'b0101: begin //发送第5位 if(clkbaud_tras) begin txd_reg <= txd_buf[0]; txd_buf[6:0] <= txd_buf[7:1]; state_tras <= state_tras + 1; end end 4'b0110: begin //发送第6位 if(clkbaud_tras) begin txd_reg <= txd_buf[0]; txd_buf[6:0] <= txd_buf[7:1]; state_tras <= state_tras + 1; end end 4'b0111: begin //发送第7位 if(clkbaud_tras) begin txd_reg <= txd_buf[0]; txd_buf[6:0] <= txd_buf[7:1]; state_tras <= state_tras + 1; end end 4'b1000: begin //发送第8位 if(clkbaud_tras) begin txd_reg<=txd_buf[0]; txd_buf[6:0]<=txd_buf[7:1]; state_tras<=state_tras+1; end end 4'b1001: begin //发送停止位 if(clkbaud_tras) begin txd_reg<=1; txd_buf<=8'h55; state_tras<=state_tras+1; end end 4'b1111:begin if(clkbaud_tras) begin state_tras<=state_tras+1; send_state<=send_state+1; trasstart<=0; case(send_state) 3'b000: txd_buf<=8'd97;//"a" 3'b001: txd_buf<=8'd32;//" " 3'b010: txd_buf<=8'd88;//"X" 3'b011: txd_buf<=8'd105;//"i" 3'b100: txd_buf<=8'd97;//"a" 3'b101: txd_buf<=8'd110;//"n" 3'b111: txd_buf<=8'd110;//"n" /* 3'b011: txd_buf<=8'd82;//"R" 3'b100: txd_buf<=8'd101;//"e" 3'b101: txd_buf<=8'd110;//"n" 3'b111: txd_buf<=8'd132;//" " */ default: txd_buf<=0; endcase end end default: begin if(clkbaud_tras) begin state_tras<=state_tras+1; trasstart<=1; end end endcase end end end //**********************************************************// always@(posedge clkbaud8x or negedge rst)//接受PC机的数据 begin if(!rst) begin rxd_reg1<=0; rxd_reg2<=0; rxd_buf<=0; state_rec<=0; recstart<=0; recstart_tmp<=0; end else begin rxd_reg1<=rxd; rxd_reg2<=rxd_reg1; if(state_rec==0) begin if(recstart_tmp==1) begin recstart<=1; recstart_tmp<=0; state_rec<=state_rec+1; end else if(!rxd_reg1&&rxd_reg2) //检测到起始位的下降沿,进入接受状态 recstart_tmp<=1; end else if(state_rec>=1&&state_rec<=8) begin if(clkbaud_rec) begin rxd_buf[7]<=rxd_reg2; rxd_buf[6:0]<=rxd_buf[7:1]; state_rec<=state_rec+1; end end else if(state_rec==9) begin if(clkbaud_rec) begin state_rec<=0; recstart<=0; end end end end always@(rxd_buf) //将接受的数据用数码管显示出来 begin case (rxd_buf) 8'h30: seg_data=8'b11000000; 8'h31: seg_data=8'b11111001; 8'h32: seg_data=8'b10100100; 8'h33: seg_data=8'b10110000; 8'h34: seg_data=8'b10011001; 8'h35: seg_data=8'b10010010; 8'h36: seg_data=8'b10000010; 8'h37: seg_data=8'b11111000; 8'h38: seg_data=8'b10000000; 8'h39: seg_data=8'b10010000; 8'h41: seg_data=8'b10001000;//a 8'h42: seg_data=8'b10000011; 8'h43: seg_data=8'b11000110; 8'h44: seg_data=8'b10100001; 8'h45: seg_data=8'b10000110; 8'h46: seg_data=8'b10001110; default: seg_data=8'b11111111; endcase end endmodule //本模块的功能是验证实现和PC机进行基本的串口通信的功能。需要在 //PC机上安装一个串口调试工具来验证程序的功能。 //程序实现了一个收发一帧10个bit(即无奇偶校验位)的串口控 //制器,10个bit是1位起始位,8个数据位,1个结束 //位。串口的波特律由程序中定义的div_par参数决定,更改该参数可以实 //现相应的波特率。程序当前设定的div_par 的值是0x145,对应的波特率是 //9600。用一个8倍波特率的时钟将发送或接受每一位bit的周期时间 //划分为8个时隙以使通信同步. //程序的工作过程是:串口处于全双工工作状态,按动key1,FPGA/CPLD向PC发送“Fa Xian" //字符串(串口调试工具设成按ASCII码接受方式);PC可随时向FPGA/CPLD发送0-F的十六进制 //数据,FPGA接受后显示在7段数码管上。
总结
洋洋洒洒写了两个晚上,很多东西都好没整理好,后面有时间会继续更新。比如,上位机通过Lora向开发板发送指令后将数据缓存到RAM中,有兴趣的同学在评论回留言: 对缓存数据有兴趣。人多的话,我会抽空写一下这个内容。
有其他问题的同学,可以加我好友,有看到会回答你的疑问,还有我们有不眠者技术交流群,可以进来互相学习。
最后
以上就是淡然水壶最近收集整理的关于基于Robei:如何利用Lora与机器人进行无线通讯日常·唠嗑:一、什么是Lora模块二、通讯方式是什么三、Robei程序设计总结的全部内容,更多相关基于Robei内容请搜索靠谱客的其他文章。
发表评论 取消回复