网站建设公司哪家好 皆来磐石网络赤壁网站建设

当前位置: 首页 > news >正文

网站建设公司哪家好 皆来磐石网络,赤壁网站建设,源码论坛下载,100大看免费行情的软件1. 在STM32F103RCT6 单片机上跑FreeRTOS 实时操作系统#xff0c;使用串口USART1 通讯#xff0c;发送 – 接收数据#xff0c;实现上位机与下位机的通信 使用 FreeRTOS 提供的队列#xff08;Queue#xff09;机制来实现数据的接收和发送

  1. USART1 配置#xff1a; …1. 在STM32F103RCT6 单片机上跑FreeRTOS 实时操作系统使用串口USART1 通讯发送 – 接收数据实现上位机与下位机的通信 使用 FreeRTOS 提供的队列Queue机制来实现数据的接收和发送
  2. USART1 配置 TX - PA9 RX - PA10 波特率9600 数据位8bit 校验位无 停止位1bit 数据格式 RX: 55 AA 06 00 06 31 02 24 01 FC 80 TX: 55 AA 06 00 06 32 01 24 01 B8 70 55 AA – 帧头 06 - 数据字节数不包括帧头不包括校验位 00 06 – 模块 31 02 24– 数据方向从上位机安卓LCD显示屏到下位机STM32 32 01 24– 数据方向从下位机STM32 到上位机安卓LCD显示屏 01 - payload 要发送的数据具体内容 FC 80 / B8 70 – CRC 16bit 校验方法计算出来的用06 00 06 31 02 24 01 使用CRC计算器可以计算出来 FC 80 CRC在线计算网址 http://www.ip33.com/crc.html3. 实现代码 #include stm32f10x.h #include FreeRTOS.h #include task.h #include queue.h#define USART1_BAUDRATE 9600 #define USART1_TX_PIN GPIO_Pin_9 #define USART1_RX_PIN GPIO_Pin_10 #define USART1_GPIO GPIOA #define USART1_GPIO_CLK RCC_APB2Periph_GPIOA #define USART1_CLK RCC_APB2Periph_USART1#define MODBUS_SLAVE_ADDR 0x01#define RX_BUF_SIZE 15 #define TX_BUF_SIZE 15static QueueHandle_t rx_queue; static QueueHandle_t tx_queue; static TaskHandle_t task_handle;void USART1_Init() {USART_InitTypeDef USART_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;// Enable clocksRCC_APB2PeriphClockCmd(USART1_CLK | USART1_GPIO_CLK, ENABLE);// Configure USART1 pinsGPIO_InitStructure.GPIO_Pin USART1_TX_PIN | USART1_RX_PIN;GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(USART1_GPIO, GPIO_InitStructure);// Configure USART1USART_InitStructure.USART_BaudRate USART1_BAUDRATE;USART_InitStructure.USART_WordLength USART_WordLength_8b;USART_InitStructure.USART_StopBits USART_StopBits_1;USART_InitStructure.USART_Parity USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART1, USART_InitStructure);// Enable USART1 interruptsUSART_ITConfig(USART1, USART_IT_RXNE, ENABLE);// Enable USART1USART_Cmd(USART1, ENABLE);// Initialize queuesrx_queue xQueueCreate(RX_BUF_SIZE, sizeof(uint8_t));tx_queue xQueueCreate(TX_BUF_SIZE, sizeof(uint8_t));// Create task for handling USART1 dataxTaskCreate(USART1_Task, USART1 Task, 1024, NULL, 1, task_handle); }void USART1_Task(void pvParameters) {while (1) {// Wait for data to be receiveduint8_t data;while (xQueueReceive(rx_queue, data, portMAX_DELAY) pdFALSE);// Process received data here// …// Send response datauint8_t resp_data[] {MODBUS_SLAVE_ADDR, / response data */};uint16_t resp_len sizeof(resp_data) / sizeof(uint8_t);xQueueSend(tx_queue, resp_data, resp_len * sizeof(uint8_t));} }void USART1_IRQHandler(void) {portBASE_TYPE xHigherPriorityTaskWoken pdFALSE;if (USART_GetITStatus(USART1, USART_IT_RXNE) ! RESET) {uint8_t data USART_ReceiveData(USART1);xQueueSendFromISR(rx_queue, data, xHigherPriorityTaskWoken);}if (USART_GetITStatus(USART1, USART_IT_TXE) ! RESET) {uint8_t data;if (xQueueReceiveFromISR(tx_queue, data, xHigherPriorityTaskWoken) pdTRUE) {USART_SendData(USART1, data);} else {USART_ITConfig(USART1, USART_IT_TXE, DISABLE);}}portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); }int main(void) {// Initialize USART1USART1_Init();// Start the schedulervTaskStartScheduler(); }在代码中首先使用 USART1_Init 函数初始化 USART1并使用 FreeRTOS 提供的 xQueueCreate 函数创建两个队列一个用于接收数据一个用于发送数据。然后使用 xTaskCreate 函数创建一个任务USART1_Task用于处理 USART1 数据。在任务中使用 xQueueReceive 函数不断等待接收数据并使用 xQueueSend 函数发送响应数据。在 USART1_IRQHandler 中使用 xQueueSendFromISR 和 xQueueReceiveFromISR 函数将接收到的数据和需要发送的数据加入相应的队列中并启用或禁用 USART1 的 TXE 中断来控制数据的发送。 需要注意的是在任务和中断中使用的队列必须定义为全局变量以避免在栈上分配空间时出现问题。另外由于 FreeRTOS 使用了抢占式调度方式因此在任务和中断中使用的队列必须具有线程安全性否则可能会导致数据丢失或者死锁等问题。 其中
  3. portBASE_TYPE xHigherPriorityTaskWoken pdFALSE;portBASE_TYPE 是 FreeRTOS 中定义的一个数据类型用于表示任务调度器是否需要进行任务切换。在 FreeRTOS 中任务调度器采用抢占式策略来决定下一次执行哪个任务。当某个任务需要让出 CPU 时间时会向任务调度器发送一个任务切换请求请求调度器立即切换到较高优先级的任务。 在 ISR 中使用 portBASE_TYPE 变量是为了确保中断服务程序能够安全地与任务调度器进行交互以避免数据竞争和死锁等问题。在 ISR 中声明和初始化一个名为 xHigherPriorityTaskWoken 的变量用于指示是否需要通知任务调度器进行任务切换。如果变量被设置为 pdTRUE则表明当前中断服务程序结束后需要调用 portEND_SWITCHING_ISR 函数以切换到更高优先级的任务如果变量被设置为 pdFALSE则表明系统无需进行任务切换可以继续执行当前任务。 当在 ISR 中完成队列操作或其他可能导致任务切换的操作时应该及时更新 xHigherPriorityTaskWoken 变量的值以确保任务调度器能够及时响应任务切换请求。同时在结束 ISR 之前也应该调用 portEND_SWITCHING_ISR 函数来通知任务调度器进行任务切换以确保多任务处理的正确性和稳定性。
  4. if (USART_GetITStatus(USART1, USART_IT_RXNE) ! RESET) {uint8_t data USART_ReceiveData(USART1);xQueueSendFromISR(rx_queue, data, xHigherPriorityTaskWoken);}这段代码是在 USART1 的中断服务程序IRQHandler中处理 USART1 的接收中断USART_IT_RXNE的。 当 USART1 接收到新的数据时会触发 USART1 的接收中断。在中断服务程序中我们首先检查 RXNERX not empty标志位是否被置位如果被置位则表明有新的数据已经接收到了。接着我们调用 USART_ReceiveData 函数从数据缓冲区寄存器中读取一个字节的数据并将其放入接收队列rx_queue中。 需要注意的是在中断服务程序中我们需要使用 xQueueSendFromISR 函数来往队列中发送数据而不能使用常规的 xQueueSend 函数。这是因为在中断服务程序中调用队列操作函数时需要确保线程安全性以避免数据竞争和死锁等问题。同时我们还需声明和初始化一个名为 xHigherPriorityTaskWoken 的变量用来指示是否需要在中断服务程序结束后调用 portEND_SWITCHING_ISR 函数以切换到更高优先级的任务。 总之这段代码用于在 USART1 中断服务程序中处理接收中断其中涉及到了队列和线程安全相关的知识点。
  5. if (USART_GetITStatus(USART1, USART_IT_TXE) ! RESET) {uint8_t data;if (xQueueReceiveFromISR(tx_queue, data, xHigherPriorityTaskWoken) pdTRUE) {USART_SendData(USART1, data);} else {USART_ITConfig(USART1, USART_IT_TXE, DISABLE);}}这段代码是在 USART1 的中断服务程序IRQHandler中处理 USART1 的发送中断USART_IT_TXE的。 当 USART1 发送数据缓冲区寄存器空TXE1时会触发 USART1 的发送中断。在中断服务程序中我们首先检查 TXE 标志位是否被设置如果被设置则表明数据缓冲区寄存器已经准备好接受新的数据进行发送。 接着我们尝试从发送队列tx_queue中取出一个字节的数据并使用 USART_SendData 函数将其发送出去。如果队列中没有数据需要发送则需要禁用 USART1 的 TXE 中断以避免不必要的中断响应。 需要注意的是在中断服务程序中我们需要使用 xQueueReceiveFromISR 函数来从队列中获取数据而不能使用常规的 xQueueReceive 函数。这是因为在中断服务程序中调用队列操作函数时需要确保线程安全性以避免数据竞争和死锁等问题。同时我们还需声明和初始化一个名为 xHigherPriorityTaskWoken 的变量用来指示是否需要在中断服务程序结束后调用 portEND_SWITCHING_ISR 函数以切换到更高优先级的任务。 总之这段代码用于在 USART1 中断服务程序中处理发送中断其中涉及到了队列和线程安全相关的知识点。
  6. portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);portEND_SWITCHING_ISR 是 FreeRTOS 提供的一个函数用于结束 ISR 并检测是否需要任务切换。在中断服务程序结束时我们需要根据变量 xHigherPriorityTaskWoken 的值来决定是否进行任务切换。 如果 xHigherPriorityTaskWoken 被设置为 pdTRUE则表明当前中断服务程序结束后需要调用 portEND_SWITCHING_ISR 函数以切换到更高优先级的任务如果 xHigherPriorityTaskWoken 被设置为 pdFALSE则表明系统无需进行任务切换可以继续执行当前任务。 当需要进行任务切换时我们调用 portEND_SWITCHING_ISR 函数将控制权交回给任务调度器并让调度器立即执行高优先级任务。具体来说portEND_SWITCHING_ISR 函数会使用 pendSV 任务向处理器发送一个软件中断信号触发任务切换流程。在此过程中调度器会检查所有任务的状态并根据任务的优先级、时间片和阻塞状态等因素来决定下一次执行哪个任务。 总之portEND_SWITCHING_ISR 函数是在中断服务程序中用于结束 ISR 并检测是否需要任务切换的重要函数。它可以确保所有任务得到合理的调度和执行从而实现高效、稳定和可靠的多任务处理。