2.54 欧派 PLS-K100 激光测距模块(来自#ifndef 的贡献)
2.54.1 模块来源
资料下载: https://pan.baidu.com/s/1v4igXEPN1c_t0kSsqZaLrg 提取码:jhpx 实物展示图
2.54.2 规格参数
工作电压:3.3V
工作电流:90mA
通信方式:UART(3.3) RS232 RS485 4~20mA
测量范围:0.03~100m(indoor) 0.03~50m(outdoor)
测量精度: 1mm(±2mm)
响应频率: 0.1~100Hz
2.54.3 模块原理
模块按照 2Hz 频率发射 635nm 的激光,通过发射与接收的时差来测量激光传输的路程.需注意这个路程,当激光射向镜面时,会导致测量误差.
2.54.4 移植工程
模块使用串口进行通信,通信速率 9600bps(8N1),模块内置 LDO,因此可在 3~5V 供电情况下通过 3.3V 电平通信.这个模块接线略麻烦,主要在模块右下角,额外注意 RXD,TXD 开漏
注意: 需要为 RX 和 TX 数据线提供上拉电阻.本例使用 4.7KR.尽管将梁山派串口初始化时启用内置上拉电阻,且示波器下波形正常,但实测模块仍无法响应,因此必须外接独立的上拉电阻.
2.54.6 移植步骤
创建 bsp_plsk100.c 文档内容如下:
/********************************************************************************
* 测试硬件:立创·梁山派开发板GD32F470ZGT6 使用主频200Mhz 晶振25Mhz
* 版 本 号: V1.0
* 修改作者: LC
* 修改日期: 2023年06月12日
* 功能介绍:
******************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:https://dri8c0qdfb.feishu.cn/docx/EGRVdxunnohkrNxItYTcrwAnnHe
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "bsp_plsk100.h"
#include "bsp_usart.h" // communication interface & log
#include <string.h>
#include "systick.h" // QA waitting
/* Private types -------------------------------------------------------------*/
/* Data struct */
typedef struct
{
/* packet struct */
uint8_t head; ///< 0xAA normal; 0xEE error
uint8_t addr; ///< device address.7bit lsb
uint16_t regnum; ///< register address num
uint16_t length; ///< length of payload(uint16_t)
uint8_t* payload; ///< payload
uint8_t checksum; ///< checksum(addr+regnum+[length]+[payload])
} Plsk100Data_t;
/* Private macros ------------------------------------------------------------*/
/* User porting interfaces */
#define PORTING_API_INIT(n) bsp_uart_user_init((n))
#define PORTING_API_SEND(dat,len) bsp_uart_user_send((dat),(len))
#define PORTING_API_RECV(dat,len) bsp_uart_user_recv((dat),(len))
#define PORTING_API_DELAY(tim) delay_1ms((tim))
#define PORTING_BUFFER_SIZE 32u
#define PLS_ADDR_DEF 0x00 // Default device address
#define PLS_ADDR_ARP 0x7F // Boardcast address
#define PLS_REG_ERR 0x0000 // system err status code
#define PLS_REG_VOL 0x0006 // power supply voltage.unit:mv DEC
#define PLS_REG_HVR 0x000A // device hardware version
#define PLS_REG_SVR 0x000C // device software version
#define PLS_REG_SNM 0x000E // device serial number
#define PLS_REG_ADD 0x0010 // device address(Write)
#define PLS_REG_OFF 0x0012 // measure result offset
#define PLS_REG_STR 0x0020 // start measure
#define PLS_REG_RES 0x0022 // measure result
#define PLS_REG_LED 0x01BE // control led(laser)
#define GET_UINT16_BE(n,b,i) \
{ \
(n) = (((uint16_t) (b)[(i)] << 8 ) | \
((uint16_t) (b)[(i) + 1] )); \
}
/* Private variables ---------------------------------------------------------*/
struct
{
bool initialize;
} Plsk100Info;
/* Private functions ---------------------------------------------------------*/
static int command_serialize( uint8_t* _Data, uint8_t _Length, bool _Read,
uint8_t _Addr, uint16_t _Reg,
uint16_t _PayLen, const uint8_t* _Payload );
static int command_deserialize( uint8_t* _Data, uint8_t _Length, Plsk100Data_t* _Msg );
static uint8_t checksumGet( const uint8_t* _Data, uint8_t _Length );
/* External variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/// @brief Initialize module
/// @return @see bsp_uart_user_init
__API__ int bsp_plsk100_init( void )
{
if( Plsk100Info.initialize != false )
{
return 0;
}
/* Initialize uart port */
if( PORTING_API_INIT( 19200 ) != 0 )
{
return -1;
}
Plsk100Info.initialize = true;
/* enable user button */
rcu_periph_clock_enable( RCU_GPIOA ); // 开启端口时钟
gpio_mode_set( GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_0 );
return 0;
}
/// @brief Get module information
/// @retval < 0 communication failure
/// @retval 0 empty
/// @retval 1 device exist
__API__ int bsp_plsk100_info( void )
{
uint8_t _buffer[PORTING_BUFFER_SIZE];
Plsk100Data_t _msg;
uint16_t _temp;
int _res;
bool _exist = false;
/* Get device hardware version */
_res = bsp_plsk100_transmit( _buffer, sizeof( _buffer ), true, PLS_ADDR_DEF,
PLS_REG_HVR, 0x00, NULL, 1000 );
if( _res < 0 || _res > 0xFF )
{
return -1;// transmit fail
}
_res = command_deserialize( _buffer, _res, &_msg );
if( _res > 0 && _msg.head == 0xAA )
{
_exist = true;
GET_UINT16_BE( _temp, _msg.payload, 0 );
LOG_RAW( "HardVersion :%04X\r\n", _temp );
}
else if( _res < 0 )
{
LOG_RAW( "Info get error %d\r\n", _res );
return _res;
}
/* Get device hardware version */
_res = bsp_plsk100_transmit( _buffer, sizeof( _buffer ), true, PLS_ADDR_DEF,
PLS_REG_SVR, 0x00, NULL, 1000 );
if( _res < 0 || _res > 0xFF )
{
return -1;// transmit fail
}
_res = command_deserialize( _buffer, _res, &_msg );
if( _res > 0 && _msg.head == 0xAA )
{
_exist = true;
GET_UINT16_BE( _temp, _msg.payload, 0 );
LOG_RAW( "SoftVersion :%04X\r\n", _temp );
}
else if( _res < 0 )
{
LOG_RAW( "Info get error %d\r\n", _res );
return _res;
}
return ( _exist ? 1 : 0 );
}
/// @brief Test fucntion
/// @return 0 Success <0 Failed
__API__ int bsp_plsk100_coroutine( void )
{
uint8_t _buffer[32];
uint8_t _value[2];
uint32_t _distance;
int _res;
Plsk100Data_t _msg;
if( gpio_input_bit_get( GPIOA, GPIO_PIN_0 ) == SET )
{
delay_1ms( 10 );
if( gpio_input_bit_get( GPIOA, GPIO_PIN_0 ) == SET )
{
/* Open laser */
_value[0] = 0x00;
_value[1] = 0x01;
bsp_plsk100_transmit( _buffer, sizeof( _buffer ), false, PLS_ADDR_DEF,
PLS_REG_LED, 0x01, _value, 0 );
/* Waitting release */
while( gpio_input_bit_get( GPIOA, GPIO_PIN_0 ) == SET );
/* Measure */
_value[0] = 0x00;
_value[1] = 0x00;
_res = bsp_plsk100_transmit( _buffer, sizeof( _buffer ), false, PLS_ADDR_DEF,
PLS_REG_STR, 0x01, _value, 1000 );
if( _res < 0 || _res > 0xFF )
{
return -1;// transmit fail
}
_res = command_deserialize( _buffer, _res, &_msg );
if( _res > 0 && _msg.head == 0xAA && _msg.length == 3 )
{
_distance = ( uint32_t )_msg.payload[0] << 24;
_distance = ( uint32_t )_msg.payload[1] << 16 | _distance;
_distance = ( uint32_t )_msg.payload[2] << 8 | _distance;
_distance = ( uint32_t )_msg.payload[3] | _distance;
LOG_RAW( "Measure result: %umm\r\n", _distance );
}
else
{
LOG_RAW( "Measure fail %d\r\n", _res );
}
/* Close laser */
_value[0] = 0x00;
_value[1] = 0x00;
bsp_plsk100_transmit( _buffer, sizeof( _buffer ), false, PLS_ADDR_DEF,
PLS_REG_LED, 0x01, _value, 0 );
return 1;
}
}
return 0;
}
/// @brief transmit command to module
/// @param[in,out] _Data data buffer
/// @param _Length length of buffer
/// @param _Read true is read command,false is write command
/// @param _Addr device address. max 0x7F
/// @param _Reg device register address
/// @param _PayLen payload length.unit: halfword
/// @param _Payload payload data
/// @param _Waiting wating for device response time.unit: ms
/// @retval <0 @see command_serialize()
/// @retval other valule,receive data length
__API__ int bsp_plsk100_transmit( uint8_t* _Data, uint8_t _Length, bool _Read,
uint8_t _Addr, uint16_t _Reg, uint16_t _PayLen,
const uint8_t* _Payload, uint32_t _Waiting )
{
int _length;
/* Read first for clear buffer */
PORTING_API_RECV( _Data, _Length );
/* Command send */
_length = command_serialize( _Data, _Length, _Read, _Addr,
_Reg, _PayLen, _Payload );
if( _length < 0 )
{
return _length; // param wrong
}
LOG_HEX( "Send->", 16, _Data, _length );
PORTING_API_SEND( _Data, _length );
/* receive response */
if( !_Waiting )
{
return 0; // Dont care response
}
PORTING_API_DELAY( _Waiting );
_length = PORTING_API_RECV( _Data, _Length );
if( _length )
{
LOG_HEX( "Recv<-", 16, _Data, _length );
}
return _length;
}
/*---- Commands --------------------------------------------------------------*/
/// @brief Serialize message
/// @param[out] _Data data buffer
/// @param _Length length of buffer
/// @param _Read true is read command,false is write command
/// @param _Addr device address. max 0x7F
/// @param _Reg device register address
/// @param _PayLen payload length.unit: halfword
/// @param _Payload payload data
/// @retval -101 data buffer too short
/// @retval >0 message length
static int command_serialize( uint8_t* _Data, uint8_t _Length, bool _Read,
uint8_t _Addr, uint16_t _Reg,
uint16_t _PayLen, const uint8_t* _Payload )
{
assert( _Data );
assert( _Addr < 0x80 );
/* Check buffer length .head+address+register+[length]+checksum = 7Byte */
if( _Length < ( ( _PayLen * 2 ) + 7 ) )
{
return -101; //Buffer too short
}
/*--- Write struct ---*/
uint8_t _len = 0;
/* Head */
_Data[_len++] = 0xAA; // Master fixed 0xAA
/* Address */
_Data[_len++] = ( ( _Read ) ? ( _Addr | 0x80 ) : ( _Addr ) );
/* Register address */
_Data[_len++] = ( uint8_t )( _Reg >> 8 );
_Data[_len++] = ( uint8_t )( _Reg );
/* Payload */
if( _PayLen )
{
/* payload length */
_Data[_len++] = ( uint8_t )( _PayLen >> 8 );
_Data[_len++] = ( uint8_t )( _PayLen );
/* payload copy */
memcpy( _Data + _len, _Payload, ( _PayLen * 2 ) );
_len += ( _PayLen * 2 );
}
/* Checksum */
_Data[_len] = checksumGet( ( const uint8_t* )_Data, _len );
return _len + 1;
}
/// @brief Deserialize message
/// @param _Data data buffer
/// @param _Length length of buffer
/// @param[out] _Msg message struct
/// @retval -101 message too short
/// @retval -102 message head wrong
/// @retval -103 message checksum fail
/// @retval >0 message length
static int command_deserialize( uint8_t* _Data, uint8_t _Length, Plsk100Data_t* _Msg )
{
assert( _Data );
uint8_t _len = 0;
memset( ( uint8_t* )_Msg, 0x00, sizeof( Plsk100Data_t ) );
/* Check packet length */
if( _Length < 5 )
{
return -101; //too short
}
/* Check Head */
if( ( _Data[_len] != 0xAA ) && ( _Data[_len] != 0xEE ) )
{
return -102; // Head fail
}
_Msg->head = _Data[_len++];
/* Address */
_Msg->addr = _Data[_len++];
/* Register */
GET_UINT16_BE( _Msg->regnum, _Data, _len );
_len += 2;
/* Payload length. min length is 4byte(2+2) */
if( _Length > ( _len + 4 ) )
{
GET_UINT16_BE( _Msg->length, _Data, _len );
_len += 2;
/* Check buffer length.1byte checksum */
if( _Length < ( _len + 1 + ( _Msg->length * 2 ) ) )
{
return -101; //too short
}
}
/* Payload */
if( _Msg->length > 0 )
{
_Msg->payload = &_Data[_len];
_len += ( _Msg->length * 2 );
}
/* Checksum */
uint8_t _checksum;
_checksum = checksumGet( ( const uint8_t* )_Data, _len );
if( _checksum != _Data[_len] )
{
LOG_RAW( "Checksum fail %02X-%02X\r\n", _Data[_len], _checksum );
return -103; //Checksum fail
}
return ( _len + 1 );
}
/// @brief Get checksum
/// @param _Data input data
/// @param _Length length of data
/// @return checksum0
static uint8_t checksumGet( const uint8_t* _Data, uint8_t _Length )
{
assert( _Data );
uint8_t _checksum = 0x00;
_Data++; //skip head byte
_Length--;
while( _Length-- )
{
_checksum += *_Data;
_Data++;
}
return ( _checksum );
}
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
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
创建 bsp_plsk100.h
文档内容如下:
/********************************************************************************
* 测试硬件:立创·梁山派开发板GD32F470ZGT6 使用主频200Mhz 晶振25Mhz
* 版 本 号: V1.0
* 修改作者: LC
* 修改日期: 2023年06月12日
* 功能介绍:
******************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:https://dri8c0qdfb.feishu.cn/docx/EGRVdxunnohkrNxItYTcrwAnnHe
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*********************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __BSP_PLSK100_H__
#define __BSP_PLSK100_H__
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Exported constants --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/// @brief Initialize module
/// @return @see bsp_uart_user_init
__API__ int bsp_plsk100_init( void );
/// @brief Get module information
/// @retval < 0 communication failure
/// @retval 0 empty
/// @retval 1 device exist
__API__ int bsp_plsk100_info( void );
/// @brief Test fucntion
/// @return 0 Success <0 Failed
__API__ int bsp_plsk100_coroutine( void );
/// @brief transmit command to module
/// @param[in,out] _Data data buffer
/// @param _Length length of buffer
/// @param _Read true is read command,false is write command
/// @param _Addr device address. max 0x7F
/// @param _Reg device register address
/// @param _PayLen payload length.unit: halfword
/// @param _Payload payload data
/// @param _Waiting wating for device response time.unit: ms
/// @retval <0 @see command_serialize
/// @retval other valule,receive data length
__API__ int bsp_plsk100_transmit( uint8_t* _Data, uint8_t _Length, bool _Read,
uint8_t _Addr, uint16_t _Reg, uint16_t _PayLen,
const uint8_t* _Payload, uint32_t _Waiting );
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __BSP_PLSK100_H__ */
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
相关串口驱动等底层驱动部分参见 bsp_usart.c
文档内容:
/********************************************************************************
* 测试硬件:立创·梁山派开发板GD32F470ZGT6 使用主频200Mhz 晶振25Mhz
* 版 本 号: V1.0
* 修改作者: LC
* 修改日期: 2023年06月12日
* 功能介绍:
******************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:https://dri8c0qdfb.feishu.cn/docx/EGRVdxunnohkrNxItYTcrwAnnHe
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*********************************************************************************/
#include "bsp_usart.h"
#include <string.h> //memcpy
/* Porting config */
// #define UARTx_BOUND 9600
#define UARTx_NAME USART1
#define UARTx_RCC RCU_USART1
#define UARTx_GPIO_RCC (RCU_GPIOA)
#define UARTx_PIN_TX GPIO_PIN_2
#define UARTx_PORT_TX GPIOA
#define UARTx_AF_TX GPIO_AF_7
#define UARTx_PIN_RX GPIO_PIN_3
#define UARTx_PORT_RX GPIOA
#define UARTx_AF_RX GPIO_AF_7
/* interrupt */
#define UARTx_IRQ_CHANNEL USART1_IRQn
#define UARTx_IRQ_HANDLER USART1_IRQHandler
#define UARTx_IRQ_PRIORITY 5
/* Revice data buffer size */
#define UARTx_RX_BUFFER_SIZE 64 // at least 9Bytes
#define MIN(n,m) (((n) < (m)) ? (n) : (m))
struct
{
bool initialize;
bool rx_flag;
uint8_t length;
uint8_t buffer[UARTx_RX_BUFFER_SIZE];
} bsp_uart_user;
__API__ int bsp_uart_user_init( uint32_t _BandRate )
{
if( bsp_uart_user.initialize != false )
{
return 0;
}
/* Enable the UART Clock */
rcu_periph_clock_enable( UARTx_GPIO_RCC );
rcu_periph_clock_enable( UARTx_RCC );
/* Configure the UART TX pin */
gpio_af_set( UARTx_PORT_TX, UARTx_AF_TX, UARTx_PIN_TX );
gpio_mode_set( UARTx_PORT_TX, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UARTx_PIN_TX );
gpio_output_options_set( UARTx_PORT_TX, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, UARTx_PIN_TX );
/* Configure the UART RX pin */
gpio_af_set( UARTx_PORT_RX, UARTx_AF_RX, UARTx_PIN_RX );
gpio_mode_set( UARTx_PORT_RX, GPIO_MODE_AF, GPIO_PUPD_PULLUP, UARTx_PIN_RX );
gpio_output_options_set( UARTx_PORT_RX, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, UARTx_PIN_RX );
/* Configure UART param: 8N1 */
usart_deinit( UARTx_NAME );
usart_baudrate_set( UARTx_NAME, _BandRate );
usart_parity_config( UARTx_NAME, USART_PM_NONE );
usart_word_length_set( UARTx_NAME, USART_WL_8BIT );
usart_stop_bit_set( UARTx_NAME, USART_STB_1BIT );
/* Enabel transmit mode */
usart_transmit_config( UARTx_NAME, USART_TRANSMIT_ENABLE );
usart_receive_config( UARTx_NAME, USART_RECEIVE_ENABLE );
/* Configure interrupt */
nvic_irq_enable( UARTx_IRQ_CHANNEL, UARTx_IRQ_PRIORITY, 0 );
/* Interrupt mode */
/* receive data not empty interrupt */
usart_interrupt_enable( UARTx_NAME, USART_INT_RBNE );
usart_interrupt_enable( UARTx_NAME, USART_INT_IDLE );
usart_flag_clear( UARTx_NAME, USART_FLAG_TC );
/* Enable periph */
usart_enable( UARTx_NAME );
bsp_uart_user.initialize = true;
return 0;
}
__API__ uint32_t bsp_uart_user_send( uint8_t* _Data, uint32_t _Length )
{
#if 0
if( USART_CTL0( UARTx_NAME ) & ( USART_CTL0_UEN ) != ( USART_CTL0_UEN ) )
{
return 0; // Device is disable
}
#else
if( bsp_uart_user.initialize == false )
{
return 0;
}
#endif
for( uint32_t i = 0; i < _Length; i++ )
{
usart_data_transmit( UARTx_NAME, *( ( char* )_Data + i ) );
while( usart_flag_get( UARTx_NAME, USART_FLAG_TC ) == RESET );
}
return _Length;
}
__API__ uint32_t bsp_uart_user_recv( uint8_t* _Data, uint32_t _Length )
{
assert( _Data );
uint32_t _len = 0;
if( bsp_uart_user.initialize == false )
{
return 0;
}
_len = MIN( _Length, bsp_uart_user.length );
if( ( bsp_uart_user.rx_flag != false ) && ( _len > 0 ) )
{
memcpy( _Data, bsp_uart_user.buffer, _len );
/* Clear receive status */
bsp_uart_user.length = 0x00;
bsp_uart_user.rx_flag = false;
}
return _len;
}
__IRQ__ void UARTx_IRQ_HANDLER( void )
{
/* Data processing after initialization */
if( bsp_uart_user.initialize != true )
{
return;
}
/* Receive Data not empty */
if( usart_interrupt_flag_get( UARTx_NAME, USART_INT_FLAG_RBNE ) != RESET )
{
/* Read one byte from the receive data register */
uint8_t _recv = ( usart_data_receive( UARTx_NAME ) & 0xFF );
/* Push one byte to receive fifo */
if( bsp_uart_user.rx_flag != false )
{
return; //Buffer data not processed, skipping reception
}
if( bsp_uart_user.length < UARTx_RX_BUFFER_SIZE )
{
// Prevent overflow
bsp_uart_user.buffer[bsp_uart_user.length++] = _recv;
}
}
/* Bus idle */
else if( usart_interrupt_flag_get( UARTx_NAME, USART_INT_FLAG_IDLE ) != RESET )
{
/* Clear IDLE */
( void )USART_STAT0( UARTx_NAME );
( void )USART_DATA( UARTx_NAME );
if( bsp_uart_user.length )
{
bsp_uart_user.rx_flag = true;
}
}
/* Overrun error : skip */
}
/*---- Log output simple apis ----------------------------------------------- */
__API__ void _LOG_HEX( char* _Name, uint8_t _Width, uint8_t* _Data, uint8_t _Length )
{
size_t _len;
for( size_t i = 0; i < _Length; i += _Width )
{
/* Name */
printf( "%-*.*s ", 16, 16, _Name );
/* Timestamp */
/* Fill data */
_len = 0x00;
for( size_t j = 0; j < _Width; j++ )
{
if( ( i + j ) < _Length )
{
printf( "%02X", _Data[i + j] );
}
if( ( j + 1 ) % 4 == 0 )
{
printf( " " );
}
}
printf( "\r\n" );
}
}
/*---- Official printf interface(KeilMDK microLib) -------------------------- */
/************************************************
函数名称 : usart_gpio_config
功 能 : 串口配置GPIO
参 数 : band_rate:波特率
返 回 值 : 无
作 者 : LC
*************************************************/
void usart_gpio_config( uint32_t band_rate )
{
/* 开启时钟 */
rcu_periph_clock_enable( BSP_USART_TX_RCU ); // 开启串口时钟
rcu_periph_clock_enable( BSP_USART_RX_RCU ); // 开启端口时钟
rcu_periph_clock_enable( BSP_USART_RCU ); // 开启端口时钟
/* 配置GPIO复用功能 */
gpio_af_set( BSP_USART_TX_PORT, BSP_USART_AF, BSP_USART_TX_PIN );
gpio_af_set( BSP_USART_RX_PORT, BSP_USART_AF, BSP_USART_RX_PIN );
/* 配置GPIO的模式 */
/* 配置TX为复用模式 上拉模式 */
gpio_mode_set( BSP_USART_TX_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, BSP_USART_TX_PIN );
/* 配置RX为复用模式 上拉模式 */
gpio_mode_set( BSP_USART_RX_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, BSP_USART_RX_PIN );
/* 配置TX为推挽输出 50MHZ */
gpio_output_options_set( BSP_USART_TX_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, BSP_USART_TX_PIN );
/* 配置RX为推挽输出 50MHZ */
gpio_output_options_set( BSP_USART_RX_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, BSP_USART_RX_PIN );
/* 配置串口的参数 */
usart_deinit( BSP_USART ); // 复位串口
usart_baudrate_set( BSP_USART, band_rate ); // 设置波特率
usart_parity_config( BSP_USART, USART_PM_NONE ); // 没有校验位
usart_word_length_set( BSP_USART, USART_WL_8BIT ); // 8位数据位
usart_stop_bit_set( BSP_USART, USART_STB_1BIT ); // 1位停止位
/* 使能串口 */
usart_enable( BSP_USART ); // 使能串口
usart_transmit_config( BSP_USART, USART_TRANSMIT_ENABLE ); // 使能串口发送
}
/************************************************
函数名称 : usart_send_data
功 能 : 串口重发送一个字节
参 数 : ucch:要发送的字节
返 回 值 :
作 者 : LC
*************************************************/
void usart_send_data( uint8_t ucch )
{
usart_data_transmit( BSP_USART, ( uint8_t )ucch ); // 发送数据
while( RESET == usart_flag_get( BSP_USART, USART_FLAG_TBE ) ); // 等待发送数据缓冲区标志置位
}
/************************************************
函数名称 : usart_send_String
功 能 : 串口发送字符串
参 数 : ucstr:要发送的字符串
返 回 值 :
作 者 : LC
*************************************************/
void usart_send_string( uint8_t* ucstr )
{
while( ucstr && *ucstr ) // 地址为空或者值为空跳出
{
usart_send_data( *ucstr++ ); // 发送单个字符
}
}
/************************************************
函数名称 : fputc
功 能 : 串口重定向函数
参 数 :
返 回 值 :
作 者 : LC
*************************************************/
int fputc( int ch, FILE* f )
{
usart_send_data( ch );
// 等待发送数据缓冲区标志置位
return ch;
}
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
2.54.7 移植验证
模块功能比较复杂,这里仅简单实现基本功能进行测量.上电初始话后会查询模块版本号,当解析出错或无响应(设备不存在)将报错并陷入死循环.通过梁山派上 KEY_UP 按键来实现可控的单次测量.
工程主函数内修改如下:
/********************************************************************************
* 测试硬件:立创·梁山派开发板GD32F470ZGT6 使用主频200Mhz 晶振25Mhz
* 版 本 号: V1.0
* 修改作者: LC
* 修改日期: 2023年06月12日
* 功能介绍:
******************************************************************************
* 梁山派软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 其余模块移植手册:https://dri8c0qdfb.feishu.cn/docx/EGRVdxunnohkrNxItYTcrwAnnHe
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
*********************************************************************************/
#include "gd32f4xx.h"
#include "systick.h"
#include "bsp_usart.h"
/* Porting files */
#include "plsk100/bsp_plsk100.h"
int main( void )
{
/* Bsp configuration */
nvic_priority_group_set( NVIC_PRIGROUP_PRE2_SUB2 );
systick_config();
usart_gpio_config( 115200U );
/* User configuration */
int _res = 0;
bool _key = false;
if( bsp_plsk100_init() != 0 )
{
LOG_RAW( "Error component initialization failed\r\n" );
delay_1ms( 5000 );
NVIC_SystemReset(); //Call software reset system
}
LOG_RAW( "Component demo start\r\n" );
_res = bsp_plsk100_info();
if( _res <= 0 )
{
LOG_RAW( "Sensor not exist or connect fail\r\n" );
for( ;; );
}
while( 1 )
{
_res = bsp_plsk100_coroutine(); // test fucntions
if( _res < 0 )
{
LOG_RAW( "Sensor error code %d\r\n", _res );
}
// delay_1ms( 500 );
}
}
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
案例现象:
上电后将打印模块的硬件版本号及软件版本号,一秒一条.按下 KEY_UP 时,模块开启激光灯指示测量点,控制模块指向待测量点后释放 KEY_UP 时将执行测量和关闭激光灯.通信过程中将输出输入数据打印出来,便于对照手册理解通信协议格式.
移植成功示例文件: