OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4724|回复: 5

刚刚学习FreeRTOS,先贴上修改原子哥的一个代码,再来请教一些系统方面的问题

[复制链接]

2

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2015-7-24
在线时间
6 小时
发表于 2016-12-7 11:42:32 | 显示全部楼层 |阅读模式
1金钱
[mw_shl_code=c,true]#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "malloc.h"
#include "string.h"
#include "adc.h"
/************************************************

************************************************/

//任务优先级
#define START_TASK_PRIO                1
//任务堆栈大小       
#define START_STK_SIZE                 256  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);

//任务优先级
#define LED0_TASK_PRIO                2
//任务堆栈大小       
#define LED0_STK_SIZE                 256
//任务句柄
TaskHandle_t LED0Task_Handler;
//任务函数
void led0_task(void *pvParameters);

//任务优先级
#define LED1_TASK_PRIO                3
//任务堆栈大小       
#define LED1_STK_SIZE                 256  
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
#define MESSAGE_Q_NUM   1           //发送数据的消息队列的数量
QueueHandle_t Message_Queue;        //信息队列句柄

int main(void)
{
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4         
        delay_init();                                            //延时函数初始化          
        uart_init(115200);                                        //初始化串口
        uart_init_2(9600);
        LED_Init();                                                          //初始化LED
//                 P_IN1=0;    //控制电机转动
//                P_IN2=1;
//                P_IN3=0;
//                P_IN4=1;
                RUN=1;
                STOP=1;
        //创建开始任务
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();          //开启任务调度
}

//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区  critical 临界的
    //创建LED0任务
        Message_Queue=xQueueCreate(MESSAGE_Q_NUM,USART_REC_LEN); //创建消息Message_Queue,队列项长度是串口接收缓冲区长度
    xTaskCreate((TaskFunction_t )led0_task,            
                (const char*    )"led0_task",          
                (uint16_t       )LED0_STK_SIZE,
                (void*          )NULL,                               
                (UBaseType_t    )LED0_TASK_PRIO,       
                (TaskHandle_t*  )&LED0Task_Handler);   
    //创建LED1任务
    xTaskCreate((TaskFunction_t )led1_task,     
                (const char*    )"led1_task",   
                (uint16_t       )LED1_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )LED1_TASK_PRIO,
                (TaskHandle_t*  )&LED1Task_Handler);         
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

//LED0任务函数
void led0_task(void *pvParameters)
{

    while(1)
    {
        LED0=~LED0;   //PC12 RUN
                                LED1=~LED1;
        vTaskDelay(500);
                //        USART_SendData(USART2, 2);
    }
}   

//LED1任务函数
void led1_task(void *pvParameters)
{
       
        u8 *buffer;
//        BaseType_t xTaskWokenByReceive=pdFALSE;
        u8 i;
    while(1)
    {
                        if(Message_Queue!=NULL)
                        {
                                buffer=mymalloc(SRAMIN,USART_REC_LEN);
                                memset(buffer,0,USART_REC_LEN);        //清除缓冲区   把buffer的前 USART_REC_LEN 个字节设置为 0
                        }
                       
                        i=xQueueReceive(Message_Queue,buffer,10);
        //                if(xQueueReceiveFromISR(Message_Queue,buffer,&xTaskWokenByReceive))
                       
                        if(xQueueReceive(Message_Queue,buffer,portMAX_DELAY))
                        {
                        i=buffer[2];
                                switch(i)
                                {
                                        case 0X31:
                                                        P_IN1=0;    //前进
                                                        P_IN2=1;
                                                        P_IN3=0;
                                                        P_IN4=1;
                                                        RUN=0;
                                                        STOP=1;                break ;
                                               
                                        case 0X32:
                                                        P_IN1=1;    //后退
                                                        P_IN2=0;
                                                        P_IN3=1;
                                                        P_IN4=0;
                                                        RUN=0;
                                                        STOP=1;                break ;
                                                       
                                        case 0X33 :
                                                        P_IN1=0;    //左
                                                        P_IN2=1;
                                                        P_IN3=0;
                                                        P_IN4=0;
                                                        RUN=0;
                                                        STOP=1;                break ;
                                                       
                                        case 0X34 :
                                                        P_IN1=0;    //右
                                                        P_IN2=0;
                                                        P_IN3=0;
                                                        P_IN4=1;
                                                        RUN=0;
                                                        STOP=1;                break ;
                                                       
                                        case 0X53 :
                                                        P_IN1=0;    //停止
                                                        P_IN2=0;
                                                        P_IN3=0;
                                                        P_IN4=0;
                                                        RUN=1;
                                                        STOP=0;                break ;
                                                               
                                }
                               
                                myfree(SRAMIN,buffer);                //释放内存
                        }
                         vTaskDelay(10);  
    }
}
[/mw_shl_code][mw_shl_code=c,true]void USART1_IRQHandler(void)                        //串口1中断服务程序
{
        u8 a;
        BaseType_t xHigherPriorityTaskWoken;
       
        if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
        {
               
                a=USART_ReceiveData(USART1);        //读取接收到的数据
                       
                USART_RX_BUF[Res++]=a;
                if(Res>=3)
                {
                Res=0;
                        Flag_message=1;
                }
        }

                if(Message_Queue!=NULL&&Flag_message==1)
        {
                Flag_message=0;
                Res=0;
                xQueueSendFromISR(Message_Queue,USART_RX_BUF,&xHigherPriorityTaskWoken);//向队列中发送数据
               
                memset(USART_RX_BUF,0,USART_REC_LEN);//清除数据接收缓冲区USART_RX_BUF,用于下一次数据接收
       
                portYIELD_FROM_ISR(xHigherPriorityTaskWoken);//如果需要的话进行一次任务切换
        }
} [/mw_shl_code]


这个是修改了原子的队列历程,然后串口接收后,通过队列发送到主函数,来判断后执行一些动作,现在程序是个小车测试用的。现在遇到的问题是,我在进行AD采集,那采集的值该怎么传倒一个任务中呢,裸机是通过全局数组,现在有了RTOS,得通过这些消息队列,信号之类的传送吗?还是说,直接全局数组也是可以的,但看原子的教程说,用全局变量会影响一些东西,那这样的话,上了系统后,编程不是变的很麻烦吗?每次要定义队列,传的时候还要申请内存之类的各种操作。。。。

最佳答案

查看完整内容[请看2#楼]

我决定用队列吧。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2016-12-7 13:14:05 | 显示全部楼层
本帖最后由 zuozhongkai 于 2016-12-7 13:16 编辑

1、采集到AD值,然后通过队列发送出去。2、即使用了系统,你依旧也可以用全局数组,但是对系统不好,使用队列的话系统会统一进行资源管理。
3、所谓的麻烦是为了系统的性能。
回复

使用道具 举报

2

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2015-7-24
在线时间
6 小时
 楼主| 发表于 2016-12-7 11:42:33 | 显示全部楼层
FreeRTOS 发表于 2016-12-7 13:53
不建议使用全局数组,如果实在要使用,在使用时也最好加临界区保护

我决定用队列吧。
回复

使用道具 举报

2

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2015-7-24
在线时间
6 小时
 楼主| 发表于 2016-12-7 11:44:16 | 显示全部楼层
刚刚看到  ,任务led1_tast,里面 i=xQueueReceive(Message_Queue,buffer,10);  这句应该注释掉的  
回复

使用道具 举报

27

主题

711

帖子

0

精华

版主

Rank: 7Rank: 7Rank: 7

积分
11922
金钱
11922
注册时间
2015-11-5
在线时间
2086 小时
发表于 2016-12-7 13:53:53 | 显示全部楼层
不建议使用全局数组,如果实在要使用,在使用时也最好加临界区保护
回复

使用道具 举报

2

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
62
金钱
62
注册时间
2015-7-24
在线时间
6 小时
 楼主| 发表于 2016-12-7 14:51:17 | 显示全部楼层
zuozhongkai 发表于 2016-12-7 13:14
1、采集到AD值,然后通过队列发送出去。2、即使用了系统,你依旧也可以用全局数组,但是对系统不好,使用队 ...

那传递AD采集的值,一般是用队列了吧,我的理解是,信号量类似裸机的标志位,传递几个数据的话就用队列?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 23:07

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表