金牌会员
- 积分
- 1108
- 金钱
- 1108
- 注册时间
- 2018-11-6
- 在线时间
- 240 小时
|
楼主 |
发表于 2020-1-21 10:55:35
|
显示全部楼层
我已经解决啦,并在STM32F103VC单片机下跑成功啦!
具体如下:
6个任务
1、任务1控制闪烁3个指示灯
2、任务2控制闪烁2个指示灯
3、任务3 采集2路DI,然后发送消息给MODBUS任务
4、任务4 采集2路DI,然后发送消息给MODBUS任务
5、任务5 每隔1秒读取一次SD2405时钟芯片的时间,然后发送消息给MODBUS任务
6、任务6 MODBUS任务,收到上位机的请求命令后,将任务3的2路DI,任务4的2路DI,任务5的SD2405时钟芯片的时间发送给上位机。
消息队列规划:
MSG[0] = 1 ---> 表示接收到上位机的请求命令
MSG[0] = 2 ---> 表示接收到任务5的的SD2405时钟芯片的时间
MSG[1] = 年
MSG[2] = 月
MSG[3] = 日
MSG[4] = 时
MSG[5] = 分
MSG[6] = 秒
MSG[7] = 星期
MSG[0] = 3 --->表示接收到任务3 采集2路DI
MSG[1] = 第1路DI
MSG[2] = 第2路DI
MSG[0] = 4 --->表示接收到任务4 采集2路DI
MSG[1] = 第1路DI
MSG[2] = 第2路DI
- /************************ Filename: platform.h *****************************/
- /* ========================================================================= */
- /* */
- /* 0000 000 000 00000 0 000 0 0 0 0000 */
- /* 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */
- /* 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Einsteinstra遝 6 */
- /* 0000 000 0 0 000 0 0 00000 0 0000 91074 Herzogenaurach */
- /* 0 00 0 0 0 0 0 0 0 0 0 */
- /* 0 0 0 0 0 0 0 0 0 0 0 0 0 Tel: ++49-9132-744-200 */
- /* 0 0 0 000 0 0 000 0 0 0 0 GmbH Fax: ++49-9132-744-204 */
- /* */
- /* ========================================================================= */
- /* */
- /* Description: User defines ( microcontroller, data types, ... ). */
- /* */
- /* ------------------------------------------------------------------------- */
- /* */
- /* Technical support: P. Fredehorst */
- /* Tel. : ++49-9132/744-214 */
- /* Fax. : -204 */
- /* eMail: pfredehorst@profichip.com */
- /* support@profichip.com */
- /* */
- /*****************************************************************************/
- /*****************************************************************************/
- /* contents:
- - header include hierarchy for system environment
- */
- /*****************************************************************************/
- /* reinclude protection */
- #ifndef PLATFORM_H
- #define PLATFORM_H
- /*****************************************************************************/
- /* reinclude-protection */
- #include "stm32f10x.h"
- #include <string.h>
- #include <stdlib.h>
- /*---------------------------------------------------------------------------*/
- /*---------------------------------------------------------------------------*/
- /* MACRO */
- /*---------------------------------------------------------------------------*/
- #define UBYTE uint8_t
- #define UWORD uint16_t
- #define BOOL uint8_t
- #define ULONG uint32_t
- /*---------------------------------------------------------------------------*/
- /*---------------------------------------------------------------------------*/
- /* MACRO */
- /*---------------------------------------------------------------------------*/
- #ifndef TRUE
- #define TRUE 1
- #endif
- #ifndef FALSE
- #define FALSE !(TRUE)
- #endif
- #define MSCOMM_BUFFER_LENGTH (255)
- #define USART1_DMA_RX_BUFFER_MAX_LENGTH (MSCOMM_BUFFER_LENGTH)
- #define USART1_DMA_TX_BUFFER_MAX_LENGTH (MSCOMM_BUFFER_LENGTH)
- #define USART2_DMA_RX_BUFFER_MAX_LENGTH (MSCOMM_BUFFER_LENGTH)
- #define USART2_DMA_TX_BUFFER_MAX_LENGTH (MSCOMM_BUFFER_LENGTH)
- #define USART3_DMA_RX_BUFFER_MAX_LENGTH (MSCOMM_BUFFER_LENGTH)
- #define USART3_DMA_TX_BUFFER_MAX_LENGTH (MSCOMM_BUFFER_LENGTH)
- #define UART4_DMA_RX_BUFFER_MAX_LENGTH (MSCOMM_BUFFER_LENGTH)
- #define UART4_DMA_TX_BUFFER_MAX_LENGTH (MSCOMM_BUFFER_LENGTH)
- #define UART5_DMA_RX_BUFFER_MAX_LENGTH (MSCOMM_BUFFER_LENGTH)
- #define UART5_DMA_TX_BUFFER_MAX_LENGTH (MSCOMM_BUFFER_LENGTH)
- #define USART6_DMA_RX_BUFFER_MAX_LENGTH (MSCOMM_BUFFER_LENGTH)
- #define USART6_DMA_TX_BUFFER_MAX_LENGTH (MSCOMM_BUFFER_LENGTH)
- //////////////////////////////////////////////////////////////////////
- //LED
- //////////////////////////////////////////////////////////////////////
- #define RCC_LED1_PORT RCC_APB2Periph_GPIOE
- #define GPIO_LED1_PORT GPIOE
- #define GPIO_LED1_Pin GPIO_Pin_6
- #define GPIO_LED1_ON() (GPIO_ResetBits(GPIO_LED1_PORT , GPIO_LED1_Pin))
- #define GPIO_LED1_OFF() (GPIO_SetBits(GPIO_LED1_PORT , GPIO_LED1_Pin))
- #define RCC_LED2_PORT RCC_APB2Periph_GPIOE
- #define GPIO_LED2_PORT GPIOE
- #define GPIO_LED2_Pin GPIO_Pin_5
- #define GPIO_LED2_ON() (GPIO_ResetBits(GPIO_LED2_PORT , GPIO_LED2_Pin))
- #define GPIO_LED2_OFF() (GPIO_SetBits(GPIO_LED2_PORT , GPIO_LED2_Pin))
- #define RCC_LED3_PORT RCC_APB2Periph_GPIOE
- #define GPIO_LED3_PORT GPIOE
- #define GPIO_LED3_Pin GPIO_Pin_4
- #define GPIO_LED3_ON() (GPIO_ResetBits(GPIO_LED3_PORT , GPIO_LED3_Pin))
- #define GPIO_LED3_OFF() (GPIO_SetBits(GPIO_LED3_PORT , GPIO_LED3_Pin))
- #define RCC_LED4_PORT RCC_APB2Periph_GPIOE
- #define GPIO_LED4_PORT GPIOE
- #define GPIO_LED4_Pin GPIO_Pin_3
- #define GPIO_LED4_ON() (GPIO_ResetBits(GPIO_LED4_PORT , GPIO_LED4_Pin))
- #define GPIO_LED4_OFF() (GPIO_SetBits(GPIO_LED4_PORT , GPIO_LED4_Pin))
- #define RCC_LED5_PORT RCC_APB2Periph_GPIOE
- #define GPIO_LED5_PORT GPIOE
- #define GPIO_LED5_Pin GPIO_Pin_2
- #define GPIO_LED5_ON() (GPIO_ResetBits(GPIO_LED5_PORT , GPIO_LED5_Pin))
- #define GPIO_LED5_OFF() (GPIO_SetBits(GPIO_LED5_PORT , GPIO_LED5_Pin))
- //////////////////////////////////////////////////////////////////////
- //DI
- //////////////////////////////////////////////////////////////////////
- //DI1----采集到高电平,行程开关状态=1;采集到低电平,行程开关状态=0。
- #define RCC_DI1_1_PORT RCC_APB2Periph_GPIOA
- #define GPIO_DI1_1_PORT GPIOA
- #define GPIO_DI1_1_Pin GPIO_Pin_4
- #define GPIO_DI1_1() ((~GPIO_ReadInputData(GPIO_DI1_1_PORT) & 0x0010) >> 4)
- //#define GPIO_DI1_1() GPIO_ReadInputDataBit(GPIO_DI1_1_PORT , GPIO_DI1_1_Pin)//((GPIO_ReadInputData(GPIO_DI1_1_PORT) & 0x0010) >> 4)//
- //DI2----采集到高电平,行程开关状态=1;采集到低电平,行程开关状态=0。
- #define RCC_DI1_2_PORT RCC_APB2Periph_GPIOA
- #define GPIO_DI1_2_PORT GPIOA
- #define GPIO_DI1_2_Pin GPIO_Pin_5
- #define GPIO_DI1_2() ((~GPIO_ReadInputData(GPIO_DI1_2_PORT) & 0x0020) >> 5)
- //#define GPIO_DI1_2() GPIO_ReadInputDataBit(GPIO_DI1_2_PORT , GPIO_DI1_2_Pin)//((GPIO_ReadInputData(GPIO_DI1_2_PORT) & 0x0020) >> 5)//
- //DI3----采集到高电平,行程开关状态=1;采集到低电平,行程开关状态=0。
- #define RCC_DI2_1_PORT RCC_APB2Periph_GPIOA
- #define GPIO_DI2_1_PORT GPIOA
- #define GPIO_DI2_1_Pin GPIO_Pin_6
- #define GPIO_DI2_1() ((~GPIO_ReadInputData(GPIO_DI2_1_PORT) & 0x0040) >> 6)
- //#define GPIO_DI2_1() ((GPIO_ReadInputData(GPIO_DI2_1_PORT) & 0x0040) >> 6)//GPIO_ReadInputDataBit(GPIO_DI2_1_PORT , GPIO_DI2_1_Pin)
- //DI4----采集到高电平,行程开关状态=1;采集到低电平,行程开关状态=0。
- #define RCC_DI2_2_PORT RCC_APB2Periph_GPIOA
- #define GPIO_DI2_2_PORT GPIOA
- #define GPIO_DI2_2_Pin GPIO_Pin_7
- #define GPIO_DI2_2() ((~GPIO_ReadInputData(GPIO_DI2_2_PORT) & 0x0080) >> 7)
- //#define GPIO_DI2_2() ((GPIO_ReadInputData(GPIO_DI2_2_PORT) & 0x0080) >> 7)//GPIO_ReadInputDataBit(GPIO_DI2_2_PORT , GPIO_DI2_2_Pin)
- //////////////////////////////////////////////////////////////////////
- //WIFIRELOAD //输出上拉 高电平---->PC7
- //WIFIREADY //输入上拉 ---->PC6
- //WIFIRESET //输出上拉 ---->PD14
- //WIFILINK //输入上拉 ---->PD15
- //////////////////////////////////////////////////////////////////////
- //WIFIRELOAD -----需要在程序中强行置为高电平
- //警告:WIFIRELOAD只能配置为输出上拉模式,程序中需要设置为高电平,即:GPIO_WIFIRELOAD_1()
- // 禁止将WIFIRELOAD设置为低电平,禁止执行GPIO_WIFIRELOAD_0(),执行GPIO_WIFIRELOAD_0()则
- // WIFI会恢复出厂缺省值。
- //WIFIRELOAD(输出)
- #define RCC_WIFIRELOAD_PORT RCC_APB2Periph_GPIOC
- #define GPIO_WIFIRELOAD_PORT GPIOC
- #define GPIO_WIFIRELOAD_Pin GPIO_Pin_7
- #define GPIO_WIFIRELOAD_0() (GPIO_ResetBits(GPIO_WIFIRELOAD_PORT , GPIO_WIFIRELOAD_Pin))
- #define GPIO_WIFIRELOAD_1() (GPIO_SetBits(GPIO_WIFIRELOAD_PORT , GPIO_WIFIRELOAD_Pin))
- //WIFIRESET(输出)
- #define RCC_WIFIRESET_PORT RCC_APB2Periph_GPIOD
- #define GPIO_WIFIRESET_PORT GPIOD
- #define GPIO_WIFIRESET_Pin GPIO_Pin_14
- #define GPIO_WIFIRESET_0() (GPIO_ResetBits(GPIO_WIFIRESET_PORT , GPIO_WIFIRESET_Pin))
- #define GPIO_WIFIRESET_1() (GPIO_SetBits(GPIO_WIFIRESET_PORT , GPIO_WIFIRESET_Pin))
- //WIFIREADY(输入)
- #define RCC_WIFIREADY_PORT RCC_APB2Periph_GPIOC
- #define GPIO_WIFIREADY_PORT GPIOC
- #define GPIO_WIFIREADY_Pin GPIO_Pin_6
- #define GPIO_WIFIREADY() (~GPIO_ReadInputDataBit(GPIO_WIFIREADY_PORT , GPIO_WIFIREADY_Pin) & 0x01) // 低电平为1,高电平为0
- //WIFILINK(输入)
- #define RCC_WIFILINK_PORT RCC_APB2Periph_GPIOD
- #define GPIO_WIFILINK_PORT GPIOD
- #define GPIO_WIFILINK_Pin GPIO_Pin_15
- #define GPIO_WIFILINK() (~GPIO_ReadInputDataBit(GPIO_WIFILINK_PORT , GPIO_WIFILINK_Pin) & 0x01) // 低电平为1,高电平为0
- //////////////////////////////////////////////////////////////////////
- //EC20_断电/供电
- //4G模块休断电/供电
- //////////////////////////////////////////////////////////////////////
- #define RCC_EC20_POWER_SLEEP_PORT RCC_APB2Periph_GPIOA
- #define GPIO_EC20_POWER_SLEEP_PORT GPIOA
- #define GPIO_EC20_POWER_SLEEP_Pin GPIO_Pin_11
- #define GPIO_EC20_POWER_SLEEP() (GPIO_ResetBits(GPIO_EC20_POWER_SLEEP_PORT , GPIO_EC20_POWER_SLEEP_Pin))
- #define GPIO_EC20_POWER_NO_SLEEP() (GPIO_SetBits( GPIO_EC20_POWER_SLEEP_PORT , GPIO_EC20_POWER_SLEEP_Pin))
- //////////////////////////////////////////////////////////////////////
- //EC20_RESET硬件复位
- //4G模块低电平复位
- //4G模块硬件复位过程如下:
- //(1)、给4G模块发送低电平------调用GPIO_EC20_RESET_0()
- //(2)、延时
- //(3)、给4G模块发送高电平------调用GPIO_EC20_RESET_1()
- //////////////////////////////////////////////////////////////////////
- #define RCC_EC20_RESET_PORT RCC_APB2Periph_GPIOA
- #define GPIO_EC20_RESET_PORT GPIOA
- #define GPIO_EC20_RESET_Pin GPIO_Pin_12
- #define GPIO_EC20_RESET_0() (GPIO_ResetBits(GPIO_EC20_RESET_PORT , GPIO_EC20_RESET_Pin))
- #define GPIO_EC20_RESET_1() (GPIO_SetBits( GPIO_EC20_RESET_PORT , GPIO_EC20_RESET_Pin))
- typedef struct
- {
- uint8_t volatile MBHosts_Query_isr;
- uint8_t volatile Outtime_mark;
- uint16_t volatile sendCount;
- uint16_t volatile sendPosi;
- uint16_t volatile receCount;
- uint8_t send_buffer[MSCOMM_BUFFER_LENGTH];
- uint8_t mscomm_buffer[MSCOMM_BUFFER_LENGTH];
- } USART_DataType;
- typedef struct
- {
- uint8_t year;
- uint8_t month;
- uint8_t day;
- uint8_t hour;
- uint8_t minute;
- uint8_t second;
- uint8_t week;
- } CLOCK_Type;
- //#else
- // #pragma message "The header PLATFORM.H is included twice or more !"
- #endif
- /*****************************************************************************/
- /* Copyright (C) profichip GmbH 2005. Confidential. */
- /*****************************************************************************/
- static TaskHandle_t xHandleTaskLED1 = NULL;
- static TaskHandle_t xHandleTaskLED2 = NULL;
- static TaskHandle_t xHandleTaskDI1 = NULL;
- static TaskHandle_t xHandleTaskDI2 = NULL;
- static TaskHandle_t xHandleTaskSD2405ALPI = NULL;
- static TaskHandle_t xHandleTaskMODBUS = NULL;
- static void LED1_Task(void *pvParameters);
- static void LED2_Task(void *pvParameters);
- static void DI1_Task(void *pvParameters);
- static void DI2_Task(void *pvParameters);
- static void SD2405ALPI_Task(void *pvParameters);
- static void MODBUS_Task(void *pvParameters);
-
- extern CLOCK_Type MODBUS_Clock;
- extern BOOL MODBUS_DI1_1;
- extern BOOL MODBUS_DI1_2;
- extern BOOL MODBUS_DI2_1;
- extern BOOL MODBUS_DI2_2;
- // 二值信号量定义
- SemaphoreHandle_t xSemaphore = NULL;
- QueueHandle_t xQueue = NULL;
- void LED1_Task(void *pvParameters)
- {
- //taskENTER_CRITICAL();
- //xTaskCreate(LED2_Task, "GPIO_LED2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 3, &xHandleTaskLED2);
- //xTaskCreate(DI1_Task, "DI1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 5, &xHandleTaskDI1);
- //xTaskCreate(DI2_Task, "DI2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 5, &xHandleTaskDI2);
- //xTaskCreate(SD2405ALPI_Task, "SD2405ALPI", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 7, &xHandleTaskSD2405ALPI);
- //xTaskCreate(MODBUS_Task, "MODBUS" , configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 9, &xHandleTaskMODBUS);
- //taskEXIT_CRITICAL();
-
- while ( 1 )
- {
- GPIO_LED1_ON();
- GPIO_LED2_ON();
- vTaskDelay(500 / portTICK_RATE_MS);
- GPIO_LED1_OFF();
- GPIO_LED2_OFF();
- vTaskDelay(250 / portTICK_RATE_MS);
- }
- }
-
- void LED2_Task(void *pvParameters)
- {
- while(1)
- {
- GPIO_LED3_ON();
- GPIO_LED4_ON();
- GPIO_LED5_ON();
- vTaskDelay(500 / portTICK_RATE_MS);
- GPIO_LED3_OFF();
- GPIO_LED4_OFF();
- GPIO_LED5_OFF();
- vTaskDelay(500 / portTICK_RATE_MS);
- }
- }
- void DI2_Task(void *pvParameters)
- {
- const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );
- BOOL DI2_1 = FALSE;
- BOOL DI2_2 = FALSE;
- uint8_t di21_array[2];
- uint8_t di22_array[2];
- uint8_t Buffer[10];
-
-
- memset(di21_array , 0x00 , 2);
- memset(di22_array , 0x00 , 2);
- while(1)
- {
- //第一次采集:采集行程2A和行程2B
- di21_array[0] = GPIO_DI2_1();
- di22_array[0] = GPIO_DI2_2();
- vTaskDelay(20 / portTICK_RATE_MS);
- //第二次采集:采集行程2A和行程2B
- di21_array[1] = GPIO_DI2_1();
- di22_array[1] = GPIO_DI2_2();
-
- if ((di21_array[0] == di21_array[1]) && (di22_array[0] == di22_array[1]))
- {
- DI2_1 = (di21_array[0] ? TRUE : FALSE);
- DI2_2 = (di22_array[0] ? TRUE : FALSE);
- }
- //函数 xQueueSend 用于任务中消息发送
- //第1个参数是消息队列句柄。
- //第2个参数要传递数据地址, 每次发送都是将消息队列创建函数 xQueueCreate 所指定的单个消息大小复制到消息队列空间中
- //第3个参数是当消息队列已经满时,等待消息队列有空间时的最大等待时间,单位系统时钟节拍。
- //返回值,如果消息成功发送返回 pdTRUE,否则返回 errQUEUE_FULL。
- //使用这个函数要注意以下问题:
- //1.FreeRTOS 的消息传递是数据的复制,而不是传递的数据地址。
- //2.此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的是xQueueSendFromISR
- //3.如果消息队列已经满且第三个参数为 0,那么此函数会立即返回。
- //4.如果用户将 FreeRTOSConfig.h 文件中的宏定义 INCLUDE_vTaskSuspend 配置为1且第三个参数配
- // 置为portMAX_DELAY,那么此发送函数会永久等待直到消息队列有空间可以使用。
- //5.消息队列还有两个函数 xQueueSendToBack 和 xQueueSendToFront,函数 xQueueSendToBack
- // 实现的是 FIFO 方式的存取,函数 xQueueSendToFront 实现的是 LIFO 方式的读写。我们这里说的函
- //数 xQueueSend 等效于 xQueueSendToBack,即实现的是 FIFO 方式的存取。
- /* 向消息队列发数据,如果消息队列满了,等待10个时钟节拍 */
- Buffer[0] = 4; //Func
- Buffer[1] = DI2_1;
- Buffer[2] = DI2_2;
-
- if( xQueueSend(xQueue, (void *) &Buffer , xTicksToWait) != pdPASS )
- {
- //发送失败,即使等待了10个时钟节拍
- }
- else
- {
- // 发送成功
- }
- vTaskDelay(100 / portTICK_RATE_MS);
- }
- }
- void DI1_Task(void *pvParameters)
- {
- const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );
- BOOL DI1_1 = FALSE;
- BOOL DI1_2 = FALSE;
- uint8_t di11_array[2];
- uint8_t di12_array[2];
- uint8_t Buffer[10];
-
-
- memset(di11_array , 0x00 , 2);
- memset(di12_array , 0x00 , 2);
- while(1)
- {
- //第一次采集:采集行程1A和行程1B
- di11_array[0] = GPIO_DI1_1();
- di12_array[0] = GPIO_DI1_2();
- vTaskDelay(20 / portTICK_RATE_MS);
- //第二次采集:采集行程1A和行程1B
- di11_array[1] = GPIO_DI1_1();
- di12_array[1] = GPIO_DI1_2();
-
- if ((di11_array[0] == di11_array[1]) && (di12_array[0] == di12_array[1]))
- {
- DI1_1 = (di11_array[0] ? TRUE : FALSE);
- DI1_2 = (di12_array[0] ? TRUE : FALSE);
- }
- //函数 xQueueSend 用于任务中消息发送
- //第1个参数是消息队列句柄。
- //第2个参数要传递数据地址, 每次发送都是将消息队列创建函数 xQueueCreate 所指定的单个消息大小复制到消息队列空间中
- //第3个参数是当消息队列已经满时,等待消息队列有空间时的最大等待时间,单位系统时钟节拍。
- //返回值,如果消息成功发送返回 pdTRUE,否则返回 errQUEUE_FULL。
- //使用这个函数要注意以下问题:
- //1.FreeRTOS 的消息传递是数据的复制,而不是传递的数据地址。
- //2.此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的是xQueueSendFromISR
- //3.如果消息队列已经满且第三个参数为 0,那么此函数会立即返回。
- //4.如果用户将 FreeRTOSConfig.h 文件中的宏定义 INCLUDE_vTaskSuspend 配置为1且第三个参数配
- // 置为portMAX_DELAY,那么此发送函数会永久等待直到消息队列有空间可以使用。
- //5.消息队列还有两个函数 xQueueSendToBack 和 xQueueSendToFront,函数 xQueueSendToBack
- // 实现的是 FIFO 方式的存取,函数 xQueueSendToFront 实现的是 LIFO 方式的读写。我们这里说的函
- //数 xQueueSend 等效于 xQueueSendToBack,即实现的是 FIFO 方式的存取。
- /* 向消息队列发数据,如果消息队列满了,等待10个时钟节拍 */
- Buffer[0] = 3; //Func
- Buffer[1] = DI1_1;
- Buffer[2] = DI1_2;
-
- if( xQueueSend(xQueue, (void *) &Buffer , xTicksToWait) != pdPASS )
- {
- //发送失败,即使等待了10个时钟节拍
- }
- else
- {
- // 发送成功
- }
- vTaskDelay(100 / portTICK_RATE_MS);
- }
- }
- void SD2405ALPI_Task(void *pvParameters)
- {
- const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );
- uint8_t Buffer[10];
- CLOCK_Type Clock;
-
- memset(Buffer , 0x00 , 10);
- bsp_InitSD2405();
-
- while(1)
- {
- SD2405_I2CReadTime(&Clock.second , &Clock.minute , &Clock.hour , &Clock.week , &Clock.day , &Clock.month , &Clock.year);
-
- //函数 xQueueSend 用于任务中消息发送
- //第1个参数是消息队列句柄。
- //第2个参数要传递数据地址, 每次发送都是将消息队列创建函数 xQueueCreate 所指定的单个消息大小复制到消息队列空间中
- //第3个参数是当消息队列已经满时,等待消息队列有空间时的最大等待时间,单位系统时钟节拍。
- //返回值,如果消息成功发送返回 pdTRUE,否则返回 errQUEUE_FULL。
- //使用这个函数要注意以下问题:
- //1.FreeRTOS 的消息传递是数据的复制,而不是传递的数据地址。
- //2.此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的是xQueueSendFromISR
- //3.如果消息队列已经满且第三个参数为 0,那么此函数会立即返回。
- //4.如果用户将 FreeRTOSConfig.h 文件中的宏定义 INCLUDE_vTaskSuspend 配置为1且第三个参数配
- // 置为portMAX_DELAY,那么此发送函数会永久等待直到消息队列有空间可以使用。
- //5.消息队列还有两个函数 xQueueSendToBack 和 xQueueSendToFront,函数 xQueueSendToBack
- // 实现的是 FIFO 方式的存取,函数 xQueueSendToFront 实现的是 LIFO 方式的读写。我们这里说的函
- //数 xQueueSend 等效于 xQueueSendToBack,即实现的是 FIFO 方式的存取。
- /* 向消息队列发数据,如果消息队列满了,等待10个时钟节拍 */
- Buffer[0] = 2; //Func
- Buffer[1] = Clock.year;
- Buffer[2] = Clock.month;
- Buffer[3] = Clock.day;
- Buffer[4] = Clock.hour;
- Buffer[5] = Clock.minute;
- Buffer[6] = Clock.second;
- Buffer[7] = Clock.week;
-
- if( xQueueSend(xQueue, (void *) &Buffer , xTicksToWait) != pdPASS )
- {
- //发送失败,即使等待了10个时钟节拍
- }
- else
- {
- // 发送成功
- }
- vTaskDelay(1000 / portTICK_RATE_MS);
- }
- }
- void MODBUS_Task(void *pvParameters)
- {
- //BaseType_t xResult;
- BaseType_t xStatus;
- const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );
- uint8_t Buffer[10];
-
-
- USART1_Configuration();
- USART1_DMA_Tx_Configuration();
- USART1_DMA_Rx_Configuration();
- while(1)
- {
- //xResult = xSemaphoreTake(xSemaphore, portMAX_DELAY);
- //if(xResult == pdTRUE)
- //{
- if( xQueue != NULL )
- {
- //函数 xQueueReceive 用于接收消息队列中的数据。
- //第 1 个参数是消息队列句柄。
- //第 2 个参数是从消息队列中复制出数据后所储存的缓冲地址,缓冲区空间要大于等于消息队列创建函
- //数xQueueCreate 所指定的单个消息大小,否则取出的数据无法全部存储到缓冲区,从而造成内存溢出。
- //第 3 个参数是消息队列为空时,等待消息队列有数据的最大等待时间,单位系统时钟节拍。
- //返回值,如果接到到消息返回 pdTRUE,否则返回 pdFALSE。
- //使用这个函数要注意以下问题:
- //1. 此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序使用的是xQueueReceiveFromISR。
- //2. 如果消息队列为空且第三个参数为 0,那么此函数会立即返回。
- //3. 如果用户将 FreeRTOSConfig.h 文件中的宏定义 INCLUDE_vTaskSuspend 配置为 1 且第三个参数配
- //置为 portMAX_DELAY,那么此函数会永久等待直到消息队列有数据。
- xStatus = xQueueReceive( xQueue, &Buffer, xTicksToWait );
- if( xStatus == pdPASS )
- {
- switch (Buffer[0])
- {
- case 1:
- USART1_Modbus_Slave_APP();
- break;
- case 2:
- MODBUS_Clock.year = Buffer[1];
- MODBUS_Clock.month = Buffer[2];
- MODBUS_Clock.day = Buffer[3];
- MODBUS_Clock.hour = Buffer[4];
- MODBUS_Clock.minute = Buffer[5];
- MODBUS_Clock.second = Buffer[6];
- MODBUS_Clock.week = Buffer[7];
- break;
- case 3:
- MODBUS_DI1_1 = Buffer[1];
- MODBUS_DI1_2 = Buffer[2];
- break;
- case 4:
- MODBUS_DI2_1 = Buffer[1];
- MODBUS_DI2_2 = Buffer[2];
- break;
- }//switch (Buffer[0])
-
- }//if( xStatus == pdPASS )
- }//if( xQueue != NULL )
- //}
- }//while(1)
- }
- int main(void)
- {
- /*
- 在启动调度前,为了防止初始化STM32外设时有中断服务程序执行,这里禁止全局中断(除了NMI和HardFault)。
- 这样做的好处是:
- 1. 防止执行的中断服务程序中有FreeRTOS的API函数。
- 2. 保证系统正常启动,不受别的中断影响。
- 3. 关于是否关闭全局中断,大家根据自己的实际情况设置即可。
- 在移植文件port.c中的函数prvStartFirstTask中会重新开启全局中断。通过指令cpsie i开启,__set_PRIMASK(1)
- 和cpsie i是等效的。
- */
- __set_PRIMASK(1);
- MB_USART1_Init();
- MB_USART2_Init();
- GPIO_Configuration();
- NVIC_Configuration();
- //创建二值信号量创建二值信号量(创建二值信号量,首次创建信号量计数值是0)
- xSemaphore = xSemaphoreCreateBinary();
- if( xSemaphore != NULL )
- {
- // 创建消息队列
- //第1个参数是消息队列支持的消息个数
- //第2个参数是每个消息的大小,单位字节。
- //返回值, 如果创建成功会返回消息队列的句柄,否则返回NULL
- //使用这个函数要注意以下问题:
- //1. FreeRTOS 的消息传递是数据的复制,而不是传递的数据地址,这点要特别注意。
- xQueue = xQueueCreate(20 , 10); //可以装载5个消息,每个消息10个字节
- if( xQueue != NULL )
- {
- //xTaskCreate(LED1_Task, "GPIO_LED1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 3 , &xHandleTaskLED1);
-
- taskENTER_CRITICAL();
- xTaskCreate(LED1_Task, "GPIO_LED1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 3 , &xHandleTaskLED1);
- xTaskCreate(LED2_Task, "GPIO_LED2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 3 , &xHandleTaskLED2);
- xTaskCreate(DI1_Task, "DI1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 5, &xHandleTaskDI1);
- xTaskCreate(DI2_Task, "DI2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 5, &xHandleTaskDI2);
- xTaskCreate(SD2405ALPI_Task, "SD2405ALPI", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 7, &xHandleTaskSD2405ALPI);
- xTaskCreate(MODBUS_Task, "MODBUS" , configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 9, &xHandleTaskMODBUS);
- taskEXIT_CRITICAL();
-
- //启动调度器
- vTaskStartScheduler();
- }
- }
- while (1);
- }
- extern QueueHandle_t xQueue;
- extern uint8_t USART1_DMA_RX_Buffer[USART1_DMA_RX_BUFFER_MAX_LENGTH];
- USART_DataType MB_USART1;
-
- //DMA中断方式
- void USART1_IRQHandler(void)
- {
- uint16_t ch;
- uint8_t Buffer[10];
- BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
-
- if (USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)
- {
- USART_ClearITPendingBit(USART1 , USART_IT_IDLE); //必须先清除总线空闲中断标识,然后读一下数据寄存器,DMA接收才会正确(先读SR,然后读DR才能清除空闲中断标识)注意:这句必须要,否则不能够清除中断标志位。
- ch = USART_ReceiveData(USART1); //必须先清除总线空闲中断标识,然后读一下数据寄存器,DMA接收才会正确(先读SR,然后读DR才能清除空闲中断标识)注意:这句必须要,否则不能够清除中断标志位。
- DMA_Cmd(DMA1_Channel5 , DISABLE); //关闭DMA,防止处理其间有数据
- DMA_ClearFlag(DMA1_FLAG_GL5 | DMA1_FLAG_TC5 | DMA1_FLAG_HT5 | DMA1_FLAG_TE5);
- ch = USART1_DMA_RX_BUFFER_MAX_LENGTH - DMA_GetCurrDataCounter(DMA1_Channel5);
- if (ch > 0)
- {
- MB_USART1.receCount = ch;
- memcpy(MB_USART1.mscomm_buffer , USART1_DMA_RX_Buffer , MB_USART1.receCount);
- }
- DMA_SetCurrDataCounter(DMA1_Channel5 , USART1_DMA_RX_BUFFER_MAX_LENGTH);
- DMA_Cmd(DMA1_Channel5, ENABLE);
-
-
- Buffer[0] = 1;
- xQueueSendToBackFromISR(xQueue , Buffer , &xHigherPriorityTaskWoken);
- portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
- }
-
- else if (USART_GetITStatus(USART1,USART_IT_TC)!= RESET)
- {
- USART_ClearITPendingBit(USART1, USART_IT_TC);
- DMA_ClearFlag(DMA1_FLAG_GL4 | DMA1_FLAG_TC4 | DMA1_FLAG_HT4 | DMA1_FLAG_TE4);
- DMA_SetCurrDataCounter(DMA1_Channel4 , 0);
- }
- }
复制代码
|
|