码迷,mamicode.com
首页 > 其他好文 > 详细

uC/OS-II在STM32F103上的移植

时间:2016-05-21 11:23:04      阅读:301      评论:0      收藏:0      [点我收藏+]

标签:

 

uc/os工程的创建和移植

先在官方下载uc/os的源代码,下载链接如下,注册之后即可以下载:

https://www.micrium.com/download/micrium_stm32xxx_ucos-ii/

注意IAR和MDK的区别,IAR版汇编的在MDK上汇编不兼容,改动会比较多。

然后在Keil中新建一个uCOS的工程,选择板子为STM32F103C8,选择CMSIS下的CORE和Device下的Startup,以及Device下的StdPeriph Drivers下的Framework,RCC,和GPIO。新建完成后可以写一个简单的LED灯的Demo测试下灯和工程是否正常。

技术分享

  关于uCOS移植到STM32(Cortex-M3)具体可以参考官方的AN-1018文档。下左图是uCOS移植到Cortex-M3的相关代码和模块之间的关系。其中最上面的是应用层,即是我们自己写的程序,然后下面是uCOS源代码,主要对应的是uCOS-II中的Src和Ports文件夹里面的代码。在工程目录和实际目录中新建Output, User和uCOS-II文件夹,分别对应上面的几个模块,其中Output用来作为工程的输出,在其中建立两个List和Obj两个文件夹,USer下用户程序,User下图的BSP模块为官方的板级支持文件,这里不需要,uCOS-II下建立两个目录Src和Ports目录,分别和源代码对应。

       然后在工程的Options的Output下,Select Foldeer for Objects,选择 Output目录下的Obj文件夹,并且同时勾选Create HEX File,Listing目录下Select Folder for Listings选择Output目录下的List文件夹。

技术分享技术分享

在工程上右击Manage Project Items,添加几个和工程目录中相同的Group。

       将Micrium\Software\uCOS-II\Ports\ARM-Cortex-M3\Generic\RealView这个文件夹中的内容拷贝到uCOS-II\uCOS-Port目录, uCOS-II\Source这个文件夹中的内容拷贝到uCOS-II \uCOS-Src目录,然后分别将其加入工程中的对应的Group中。为了uCOS的源代码被误改,可以将uCOS的Src目录下的文件设置成只读。

       将Micrium\Software\EvalBoards\ST\STM3210B-EVAL\RVMDK\OS-Probe目录下的app_cfg.h,os_cfg.h和includes.h文件拷贝到User目录下,加入对应Group中,并且在User中添加入一个应用程序文件app.c。最终代码结构可见上图。

       为了所有的能够直接include,将图中以下的目录添加到Options的C/C++标签下面的Include Paths中,并在Define中加上USE_STDPERIPH_DRIVER.

技术分享

  修改os_cfg.h文件,#define OS_APP_HOOKS_EN 1为0,禁用钩子函数。

     编译之后会提示os_cpu_c.c文件中OS_CPU_SysTickClkFreq函数没有定义,这里可以之间将其改正72MHZ(Cortex-M3),当然如果为了更好的适配性,可以将其改成system_stm32f10x.c文件下的一个变量SystemCoreClock。

技术分享

重新编译,发现includes.h中很多文件不存在,直接将其注释掉即可。

技术分享

上面只是一些简单的文件的复制,而要将ucos移植到stm32还需要使他们建立联系。uCOS-II的核心就是任务调度,其必须使用STM32的一个PendSV这个中断,其实这个就是小作业中做过的Cortex-M3的uCOS的任务切换函数。还有就是uCOS-II需要一个基准时间,其使用STM32中的一个专为操作系统设置的定时器SysTick。比较简单的解决方案是,在启动文件startup_stm32f10x_md.s中将所有的PendSV_Handler全部替换成为OS_CPU_PendSVHandler, SysTick_Handler 替换成OS_CPU_SysTickHandler,每个各有三处。也可以采用网上说的在外面实现这两个函数。

       这样就完成了uCOS到STM32的整个移植过程。

 

uc/os对GPIO的访问

对于GPIO的访问,这里采用了点亮LED灯的方式进行实现。

在app.c中写入一些的代码,其新建了两个任务,分别对应用来点亮两个LED灯。系统首先进行初始化,然后创建两个任务。

 1 #include "includes.h"
 2 #include "ucos_ii.h"
 3 #define LED0STKSIZE 1000
 4 #define LED1STKSIZE 1000
 5 
 6 void LED_GPIO_Init(void)
 7 {
 8     GPIO_InitTypeDef GPIO_InitStruct;
 9     RCC_DeInit();
10     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
11     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;    
12     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
13     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
14     GPIO_Init(GPIOA, &GPIO_InitStruct);
15 }    
16 
17 void Task_LED0(void *p_arg)
18 {
19     while(1)
20     {
21         GPIO_SetBits(GPIOA, GPIO_Pin_9);    //on
22         OSTimeDly(50);                    //half second
23         GPIO_ResetBits(GPIOA, GPIO_Pin_9);    //off
24         OSTimeDly(50);
25     }
26 }
27 
28 void Task_LED1(void *p_arg)
29 {
30     while(1)
31     {
32         GPIO_SetBits(GPIOA, GPIO_Pin_10);    //on
33         OSTimeDly(100);    //one second
34         GPIO_ResetBits(GPIOA, GPIO_Pin_10);    //off
35         OSTimeDly(100);
36     }
37 }
38 
39 OS_STK LED0TaskStk[LED0STKSIZE];
40 OS_STK LED1TaskStk[LED1STKSIZE];
41 int main()
42 {
43     LED_GPIO_Init();    //initialize the gpio
44     OSInit();                    //initialize the os
45     OS_CPU_SysTickInit();    //initialze the system clock
46     //create two task LED0 and LED1
47     OSTaskCreate(Task_LED0, (void *)0, &LED0TaskStk[LED0STKSIZE - 1], 5);
48     OSTaskCreate(Task_LED1, (void *)0, &LED1TaskStk[LED1STKSIZE - 1], 6);
49     OSStart();    //start the os
50     return 0;
51 }

 

将LED等连接到好之后,下载观察到两盏小灯闪烁

 技术分享

 

七段数码管的显示

 技术分享

LG3641BH的引脚图如上面两幅图所示,其中A-G分别对应一个数字的七段(A-G对应如右图所示),DP表示小数点,D1-D4表示位选信号。

每次我们只需要通过位选信号来显示一个数字即可以,然后利用时分复用的原理依次快速点亮其他的数字,使得人眼看起来是同时亮起来的。

实验中采用了GPIO的PA0-7引脚作为七段数码端的7段以及DP,PA9-12作为四个位选信号D1-D4。

下面为七段数码管的显示代码,digitSel为位选设置,通过传入的一个位选信号,设置PA9-12这几个位选信号的值。digitDisp为显示信号,根据传入的一个 数字以及小数点然后设置PA0-7这几个GPIO的值。

TaskDisp为显示七段数码管的任务,其中不断的扫描每一位数字,使得人眼看上去是一起显示的。这里需要注意的是由于位选控制和数字显示有前后之分,因此会出现某一个变化了另一个还没有变化的情况,因此这里将时间比较长的数字显示放在前面以此缩短两个GIPO的不统一的时间。而且后面加上了一个循环7000的延时,如果采用uCOS自带的定时函数,由于其精度太低,会出现闪烁,而如果这个计数设置的过小,则会出现重影。

TaskInc为value的递增任务,没个1秒其增加1,而且其任务的优先级需要比TaskDisp高,否则其不会得到执行。

  1 #include "includes.h"
  2 #include "ucos_ii.h"
  3 
  4 #define LED0STKSIZE 1000
  5 #define LED1STKSIZE 1000
  6 
  7 void GPIO_Config(void)
  8 {
  9     GPIO_InitTypeDef GPIO_InitStruct;
 10     RCC_DeInit();
 11     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
 12     
 13     //digit select
 14     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
 15     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
 16     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
 17     GPIO_Init(GPIOA, &GPIO_InitStruct);
 18 
 19     //7-segment and one point
 20     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 |
 21                                                          GPIO_Pin_1 |
 22                                                        GPIO_Pin_2 |
 23                                                          GPIO_Pin_3 |
 24                                                          GPIO_Pin_4 |
 25                                                        GPIO_Pin_5 |
 26                                                        GPIO_Pin_6 |
 27                                                        GPIO_Pin_7 ;
 28     
 29     GPIO_Init(GPIOA, &GPIO_InitStruct);
 30 }
 31 
 32 void digitSel(int sel)
 33 {
 34         uint16_t pinSel[] = {GPIO_Pin_9, GPIO_Pin_10, GPIO_Pin_11, GPIO_Pin_12};
 35         int i = 0;
 36         for(;i<4;++i)
 37         {
 38             if(sel == i)
 39                 GPIO_SetBits(GPIOA, pinSel[i]);
 40             else
 41                 GPIO_ResetBits(GPIOA, pinSel[i]);
 42         }
 43 }
 44 
 45 void digitDisp(int digit, int point)
 46 {
 47     int node, i;
 48     uint16_t pinSel[] = {GPIO_Pin_0, GPIO_Pin_1, GPIO_Pin_2, GPIO_Pin_3,GPIO_Pin_4, GPIO_Pin_5, GPIO_Pin_6, GPIO_Pin_7};
 49     int sel = 1<< 7;
 50     
 51     switch (digit)
 52     {
 53         case 0 : node = 0xFC; break; // 11111100
 54     case 1 : node = 0x60; break; // 01100000
 55     case 2 : node = 0xDA; break; // 11011010
 56     case 3 : node = 0xF2; break; // 11110010
 57     case 4 : node = 0x66; break; // 01100110
 58     case 5 : node = 0xB6; break; // 10110110
 59     case 6 : node = 0xBE; break; // 10111110
 60     case 7 : node = 0xE0; break; // 11100000
 61     case 8 : node = 0xFE; break; // 11111110
 62     case 9 : node = 0xF6; break; // 11110110
 63     default: node = 0x9E; break; // 10011110 error and display E to represent error
 64    }
 65      node |= (point != 0);
 66      
 67      for(i=0;i<8;i++)
 68      {
 69         if((node & sel) == 0)
 70             GPIO_SetBits(GPIOA, pinSel[i]);
 71         else
 72             GPIO_ResetBits(GPIOA, pinSel[i]);
 73         
 74         sel >>= 1;
 75      }
 76 }
 77 
 78 int value = 0;
 79 void TaskDisp(void *p_arg)
 80 {
 81     int i, base, cnt = 7000;
 82     while(1)
 83     {
 84         base = 1000;
 85         for(i=0;i<4;i++)
 86         {
 87             digitDisp((value/base)%10, 0);
 88             digitSel(i);
 89             base /= 10;
 90             while(cnt--);
 91             cnt = 8000;
 92         }
 93     }
 94 }
 95 
 96 void TaskInc(void *p_arg)
 97 {
 98     while(1)
 99     {
100         value++;
101         value %= 10000;
102         OSTimeDly(100);
103     }
104 }
105 
106 OS_STK TaskStk1[LED0STKSIZE];
107 OS_STK TaskStk2[LED1STKSIZE];
108 
109 int main()
110 {
111     GPIO_Config();    //initialize the gpio
112 
113     OSInit();                    //initialize the os
114     OS_CPU_SysTickInit();    //initialze the system clock
115     
116     //create two task LED0 and LED
117     OSTaskCreate(TaskDisp, (void *)0, &TaskStk1[LED0STKSIZE - 1], 5);
118     OSTaskCreate(TaskInc, (void *)0, &TaskStk2[LED0STKSIZE - 1], 4);
119     OSStart();    //start the os
120     
121     return 0;
122 }

运行之后download观看显示结果(显示的测试显示的1234和5678的结果)

技术分享技术分享

 

uC/OS-II在STM32F103上的移植

标签:

原文地址:http://www.cnblogs.com/jackwang822/p/5514168.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!