在网上看到的ucos的示例程序,很多都是点灯之类的。参考的价值不是很大。
近阶段在stm32上研究uc,写了个程序如下。
程序功能:
(1)通过串口中断接收命令,模拟键盘效果。
(2)通过触发事件使串口对外发送数据
(3)can接收中断触发消息发送,最终触发串口对外发送数据
(4)定时器4中断计数,串口对外发送计数值。
#include "STM32Lib\\stm32f10x.h"
#include "hal.h"
#include "UCOSII\\ucos_ii.h"
#include "stm32f10x_it_my.h"
#include "stdio.h"
#include "string.h"
extern unsigned int count;
extern volatile bool ADC_Ok;
extern u16 ADCCov[16];
extern void DMAReConfig(void);
/******************************
** 任务堆栈
*******************************/
OS_STK Task0Stk[128];
OS_STK task1_stk[128];
OS_STK task2_stk[128];
OS_STK task_key_stk[128];
OS_STK task3_stk[128];
OS_STK task4_stk[128];
OS_STK task5_stk[128];
OS_STK task6_stk[128];
OS_STK task_can_rx_stk[128];
OS_STK task_uart_tx_stk[128];
/******************************
任务函数
******************************/
void Task0(void *prg);
void task_key(void *prg);
void my_task1(void *prg);
void my_task2(void *prg);
void my_task3(void *prg);
void my_task4(void *prg);
void my_task5(void *prg);
void my_task6(void *prg);
void task_uart_tx(void * prg);
OS_EVENT *mysem[10];
OS_EVENT *sem;
OS_EVENT *mybox;
//串口输出重定向,使printf输出重定向
int fputc(int ch, FILE *f)
{
//USART_SendData(USART1, (u8) ch);
USART1->DR = (u8) ch;
/* Loop until the end of transmission */
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
{
}
return ch;
}
/**************************************************************
** 函数名:DigitFilter
** 功能:软件滤波
** 注意事项:取NO的2/5作为头尾忽略值,注意N要大于5,否则不会去头尾
***************************************************************/
u16 DigitFilter(u16* buf,u8 no)
{
u8 i,j;
u16 tmp;
u8 cut_no=0;
//排序
for(i=0;i {
for(j=0;j {
if(buf[j]>buf[j+1])
{
tmp=buf[j];
buf[j]=buf[j+1];
buf[j+1]=tmp;
}
}
}
if(no>5)
{
cut_no=no/5;
}
//平均
tmp=0;
for(i=cut_no;i tmp+=buf[i];
return(tmp/(no-2*cut_no));
}
int main(void)
{
u8 os_err;
os_err=os_err;
//由于使用UCOS,一下的初始化虽然可以在OS运行之前运行,但注意别使能任何中断.
ChipHalInit(); //片内硬件初始化
ChipOutHalInit(); //片外硬件初始化
CAN_Interrupt();
OSInit(); //UCOS INIT~
os_err = OSTaskCreate( Task0, //第一个任务0
(void * ) 0, //不带参数
(OS_STK * )&Task0Stk[128 - 1], //堆栈指针
(INT8U ) 5 //优先级
);
OSStart();
while(1);
}
//任务1主要用来创建各个实现子功能的任务快
void Task0(void *p_arg)
{
u8 os_err;
os_err=os_err;
// char DATA_1[]="TASK1_ON\r\n";
OS_CPU_SysTickInit(); //使能SYSTICK中断
#if (OS_TASK_STAT_EN > 0)
OSStatInit(); /*这东西可以测量CPU使用量 */
#endif
os_err= OSTaskCreate( my_task1,
(void *)0,
(OS_STK *)&task1_stk[128-1],
(INT8U )19
);
os_err= OSTaskCreate( my_task2,
(void *)0,
(OS_STK *)&task2_stk[128-1],
(INT8U )9
);
os_err= OSTaskCreate( task_key,
(void *)0,
(OS_STK *)&task_key_stk[128-1],
(INT8U )7
);
os_err= OSTaskCreate( my_task4,
(void *)0,
(OS_STK *)&task4_stk[128-1],
(INT8U )29
);
os_err= OSTaskCreate( my_task5,
(void *)0,
(OS_STK *)&task5_stk[128-1],
(INT8U )44
);
os_err= OSTaskCreate( task_uart_tx,
(void *)0,
(OS_STK *)&task_uart_tx_stk[128-1],
(INT8U )6
);
os_err=OSTaskCreate(my_task6,
( void *) 0,
(OS_STK *)&task6_stk[128-1],
(INT8U )45
);
for(;;)
{
OSTimeDly(OS_TICKS_PER_SEC/10);
}
}
//接收到can中断服务子函数发送的消息,通过串口对外发送CAN RECEIVED
void task_uart_tx(void * prg)
{
INT8U err;
box_can_rx=OSMboxCreate((void *)0);
while(1)
{
OSMboxPend(box_can_rx,0,&err);
USART1_Puts("CAN RECEIVED!\r\n");//(char *)uart_buff
OSTimeDly(OS_TICKS_PER_SEC/10);
}
}
//通过串口接收中断模拟键盘的功能
void task_key(void *prg)
{
INT8U baud='4';
INT8U os_err;
os_err=os_err;
mysem[1]=OSSemCreate(0);//创建信号量
mysem[2]=OSSemCreate(0);//创建信号量
sem=OSSemCreate(0);
mybox=OSMboxCreate((void *)0);
while(1)
{
switch(uart_cmd_buf)
{
case '1':
{
//发送信号量
OSSemPost(mysem[1]);
}break;
case '2':
{
OSSemPost(mysem[2]);
}break;
case '3':
{
os_err=OSTaskCreate( my_task3,
(void * )0,
(OS_STK * )&task3_stk[128 - 1], //堆栈指针
(INT8U ) 8 //优先级
);
}break;
case '4':
{
OSMboxPost(mybox,&baud);
}break;
case '5':
{
os_err= OSTaskCreate( my_task5,
(void *)0,
(OS_STK *)&task5_stk[128-1],
(INT8U )18
);
}break;
}
uart_cmd_buf=0;
OSTimeDly(OS_TICKS_PER_SEC/10);
}
}
//任务1和任务2进行双向同步,在串口接收到‘1’或者‘2’,任务1和任务2开始运行起来
void my_task1(void *prg)
{
INT8U err;
while(1)
{
OSSemPend(mysem[1],0,&err);
USART1_Puts("m1\r\n");
OSSemPost(mysem[2]);
OSTimeDly(OS_TICKS_PER_SEC/10);
}
}
void my_task2(void *prg)
{
INT8U err;
while(1)
{
OSSemPend(mysem[2],0,&err);
USART1_Puts("m2\r\n");
//printf("%dp\r\n",OSCPUUsage);
OSSemPost(mysem[1]);
OSTimeDly(OS_TICKS_PER_SEC/10);
}
}
//对外发送“m3”
void my_task3(void *prg)
{
//INT8U err;
while(1)
{
USART1_Puts("m3\r\n");
OSTimeDly(OS_TICKS_PER_SEC/10);
}
}
//接收到消息后,对外发送baud,即‘4’
void my_task4(void *prg)
{
INT8U err;
char baud;
err=err;
prg=prg;
while(1)
{
baud=*(char *)OSMboxPend(mybox,0,&err);
printf("%s\r\n",&baud);
OSTimeDly(OS_TICKS_PER_SEC/10);
}
}
//AD转换任务,将ad值串口发送出去
void my_task5(void *prg)
{
u16 adc;
while(1)
{
// printf("cnt is %d\r\n",count);
/* 人工打开ADC转换.*/
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
if(ADC_Ok==TRUE)
{
ADC_Ok=FALSE;
adc=DigitFilter(ADCCov,16); //滤波
DMAReConfig();//重新启动DMA
adc=(1.42 - adc*3.3/4096)*1000/4.35 + 25;//转换为温度值,实际应用中,可考虑用毫伏为单位,避免浮点运算
ADC_SoftwareStartConvCmd(ADC1, DISABLE);
printf("当前温度是:%d\r\n",adc);
}
OSTimeDly(OS_TICKS_PER_SEC/10);
}
}
//将CPU的利用率串口输出
void my_task6(void *prg)
{
while(1)
{
printf("cpu usage is: %d\r\n",OSCPUUsage);
//printf("%d p\r\n",OSCPUUsage);
//USART1_Puts("%d p\r\n");
OSTimeDly(OS_TICKS_PER_SEC/10);
}
}
需要说明的是,由于板子上只有uart和can,所以一切的任务都是基于这两个通信接口。