# Chhol_STM32 **Repository Path**: lee8871/chhol_stm32 ## Basic Information - **Project Name**: Chhol_STM32 - **Description**: 使用STM32微控制器,与斥候无线模块通信的例程。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 0 - **Created**: 2024-08-01 - **Last Updated**: 2025-12-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 斥候无线模块-STM32开发例程包 这是使用STM32连接斥候模块进行无线组网通信的演示程序。 斥候(Chhol)模块的命令串口使用**CC9D协议**,外接的STM32微控制器需要实现此协议, 将带有地址信息的数据告知斥候模块,即可完成组网通信。 ## 程序集说明 |路径|说明| | -----------------| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |BSP|BSP,即板级支持包(Board Support Package),包含了和电路板与硬件相关的程序。具体来说,有Uart、LED、调试串口(用与printf输出程序)、和系统定时器。| |Chhol|斥候无线模块相关的程序,这部分程序和硬件无关。
其中CC9D协议支持用于理解和构造与斥候模块通信的数据包;
Crc8用于完成CC9D中需要的循环冗余校验;
byte_queue是串口缓冲队列,用于暂存串口收发需要的数据。| |Libraries|由`STMicroelectronics`​提供的库函数。| |chhol_base_demo|基础通信的例程,可以完成简单的数据收发。| |chhol_adc_report|ADC采集上报例程,可以采集ADC值,定制上报,在ADC值大幅变化后也会上报。| ## chhol_base_demo介绍 这一演示程序使用常见的STM32开发板搭建,微控制器使用uart连接到斥候模块,和另一个斥候模块进行通信。 在这一演示中 ### 硬件接线 ​![第一个demo的实物情况](assets/第一个demo的实物情况-20240802065355-8a332qy.png)​ 其接线包括: |GPIO编号|外部连接到|MCU内的功能| | ----------| ----------------------------------------------------| -----------------------------------------------------| |A5|红色LED|GPIO,控制红色LED的开关| |A6|黄色LED|GPIO,控制黄色LED的开关| |A7|绿色LED|GPIO,控制绿色LED的开关| |C13|蓝色LED|GPIO,控制蓝色LED的开关| |A2|斥候模块命令串口RX|USART2_TX,串口发送引脚| |A3|斥候模块命令串口TX|USART2_RX,串口接收引脚| |A9|USB转Uart的Rx|USART1_TX,串口发送引脚,用于printf| |A10|USB转Uart(未连接)|USART1_RX,串口接收引脚,用于接收指令,现在未连接。| ### 软件介绍 整个系统的软件构成如下图: ​![image](assets/image-20240803061626-5qgwyo5.png)​ ### 接收无线包并处理 收到任何包后,CC9D会调用`sCc9dPkg* _cc9d_receivePkg(sCc9dPkg* pkg, uint8 data_len)`​在这个函数中,应当根据收到包的信息,选择接收的处理程序: ```c sCc9dPkg* _cc9d_receivePkg(sCc9dPkg* pkg, uint8 data_len) { switch (pkg->to_port) { case 16://将16号端口分配给LED,因此,从此处收到的数据需要发给 ledControl(pkg, data_len); break; default://应该避免给模块发送目的端口号没有使用的包。 printf("Reserved port %d get a pkg, from %X.%d\n\tdatas: ", pkg->to_port, pkg->remote_addr, pkg->from_port); for(int i=0;idatas[i]); } printf("\n"); break; } //返回pkg,意味着在退出此函数后CC9D继续使用pkg接收下一个包。 //如果程序中还要继续使用pkg中的数据,则必须准备一个未用的包指针,以供CC9D接收数据。 return pkg; } ``` ### 无线发出包 可以在任何程序序列中进行发送包,发送时需要进行以下操作: 1. 准备发送包结构体。 2. 填入地址和端口信息。 3. 填入数据。 4. 使用`void cc9d_SendPkg(sCc9dPkg pkg_mem_type* pkg, uint8 data_len)`​进行发送,并以参数提供之前构建的结构体和需要发送的数据的长度。 发送的程序看起来是这样的: ```c sCc9dPkg send_pkg;//发送包的数据体 send_pkg.from_port = 32;//源端口号 send_pkg.to_port = 32;//目的端口号 send_pkg.remote_addr = 0x0000;//目的地址 send_pkg.datas[0] = (sno >> 0) & 0xff; send_pkg.datas[1] = (sno >> 8) & 0xff; send_pkg.datas[2] = 0x56; send_pkg.datas[3] = 0x78; cc9d_SendPkg(&send_pkg,4);//调用这个函数,进行发送,第二个参数是数据部分的长度,单位是byte。 ``` ​`cc9d_SendPkg`​函数不会占用`send_pkg`​空间,在`cc9d_SendPkg`​返回后就可以释放`send_pkg`​占用的空间。 另外需要注意,`cc9d_SendPkg`​不是线程安全的,如果在中断线程和主线程内都会调用`cc9d_SendPkg`​,就需要在调用前后添加临界区。 ### 关于队列 在此程序中,广泛用到了循环队列。队列可以先接收多个字节并保存,过后在需要数据时,按顺序将数据取出。 在Uart接收数据时,在Uart的中断线程内,将数据存入队列,而后主线程中合适的位置,将数据取出并使用; 在Uart发送数据时,可以在主线程中连续的将大量字节写入队列,并开启发送中断;在中断线程中,每当一个字节发送回完成,就从队列中取出下一个字节发送,直到发送完成。 在 Uart2的接收和发送事物,以及printf的发送事务中,用到了队列。 需要注意,如果一次发送了过多数据,或者长时间没有从接收队列中取出数据,造成队列中储存超过其容量的数据,就会造成数据丢失。 可以在程序中设置队列的容量,其容量必须是2的整数幂。 ```c //串口收发缓冲区 static uint8 tx_buf[256]; static sByteQueue tx_queue; static uint8 rx_buf[256]; static sByteQueue rx_queue; //串口缓冲区初始化 static void initQueue(void) { //初始化这两个队列 ByteQueue_init(&tx_queue, tx_buf, 256); ByteQueue_init(&rx_queue, rx_buf, 256); } ``` ```c static uint8 tx_buf[256]; static sByteQueue u1tx_queue; static void initQueue(void) { //初始化这两个队列 ByteQueue_init(&u1tx_queue, tx_buf, 256); } ``` 在程序中,队列的长度都被设置为256字节,实际可以存放255字节数据。 ### 演示现象 将0002节点连接到STM32,0000连接到电脑,可以看到STM32每个2秒发送一个包。![image](assets/image-20240803070516-6wcyp17.png)​ 发送命令到0002.16,可以控制LED点亮: |命令|效果| | -----------| -------------| |0002.16:1|红色LED点亮| |0002.16:2|黄色LED点亮| |0002.16:3|绿色LED点亮| ​​ ‍