历史上的今天
今天是:2024年11月02日(星期六)
2021年11月02日 | stm32实用篇2: 裸机系统实现多任务轮转
2021-11-02 来源:eefocus
在裸机系统中,通常都是在一个大的 while 循环中,通过判断标志位,来按照顺序执行相应的代码。为了加快响应速度,较为常见的做法是中断中修改标志位,代码中判断标志位,如下所示:
int main(void)
{
XX_Init();
/* while 中判断标志位 */
while (1)
{
if (flag0 == 1)
{
code0;
flag0 = 0;
}
if (flag1 == 1)
{
code1;
flag1 = 0;
}
/************/
}
}
/* 中断服务函数中修改标志位 */
void Handler0(void)
{
flag0 = 1;
}
void Handler1(void)
{
flag1 = 1;
}
上述处理在裸机系统中比较常用,也足以实现很多的功能。但一种更为高级的处理方式,就是利用 SysTick 来实现类似于实时操作系统的调度,来看一下是怎么实现的:
/* 定义2个任务 */
#define NumOfTask 2
/* 任务的时基数组,由SysTick中断服务函数更新 */
unsigned int Task_Delay[NumOfTask]={ 0 };
int main(void)
{
XX_Init();
/* 开启系统滴答定时器 */
SysTick_Init();
/* 所有的任务会按照延时,准时唤醒执行 */
while (1)
{
if (Task_Delay[0] == 0)
{
/* 任务 0 主体 */
Task(0);
/* 任务 0 延时 1000ms */
Task_Delay[0] = 1000;
}
if (Task_Delay[1] == 0)
{
/* 任务 1 主体 */
Task(1);
/* 任务 1 延时 500ms */
Task_Delay[1] = 500;
}
/* 下面是增加任务的格式 */
if (Task_Delay[i] == 0)
{
/* 任务 i 主体 */
Task(i);
/* 任务 i 延时 */
Task_Delay[1] =
}
}
}
/* 滴答定时器中断服务函数中对所有任务更新时基 */
void SysTick_Handler(void)
{
unsigned char i;
for (i = 0; i < NumOfTask; i++)
{
if (Task_Delay[i])
{
Task_Delay[i]--;
}
}
}
接下来是一个参考代码,主要实现的功能是,led灯 1 秒状态翻转一次(任务1),串口 0.5 秒打印一次数据(任务)2。
#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include "./systick/bsp_SysTick.h"
#include "./led/bsp_led.h"
#include "./usart/bsp_usart.h"
#include "./mpu6050/mpu6050.h"
#include "./i2c/bsp_i2c.h"
#define TASK_ENABLE 0
extern unsigned int Task_Delay[NumOfTask];
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
short Acel[3];
short Gyro[3];
float Temp;
SysTick_Init();
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;
/* LED 端口初始化 */
LED_GPIO_Config();
/* 串口通信初始化 */
USART_Config();
//I2C初始化
I2C_Bus_Init();
//MPU6050初始化
MPU6050_Init();
//检测MPU6050
if (MPU6050ReadID() == 1)
{
while(1)
{
if(Task_Delay[0] == 0)
{
LED2_TOGGLE;
Task_Delay[0]=1000;
}
if(Task_Delay[1] == 0)
{
MPU6050ReadAcc(Acel);
printf("加速度:%8d%8d%8d",Acel[0],Acel[1],Acel[2]);
MPU6050ReadGyro(Gyro);
printf(" 陀螺仪%8d%8d%8d",Gyro[0],Gyro[1],Gyro[2]);
MPU6050_ReturnTemp(&Temp);
printf(" 温度%8.2frn",Temp);
/* 更新一次数据,可根据自己的需求,提高采样频率,如100ms采样一次 */
Task_Delay[1]=500;
}
* 下面是增加任务的格式 *
if(Task_Delay[i] == 0)
{
Task(i);
Task_Delay[i]=;
}
}
}
else
{
printf("rn没有检测到MPU6050传感器!rn");
LED_RED;
while(1);
}
}
/**
* @brief 启动系统滴答定时器 SysTick
* @param 无
* @retval 无
*/
void SysTick_Init(void)
{
/* SystemFrequency / 1000 1ms中断一次
* SystemFrequency / 100000 10us中断一次
* SystemFrequency / 1000000 1us中断一次
*/
if (SysTick_Config(SystemCoreClock/1000))
{
/* Capture error */
while (1);
}
// 关闭滴答定时器
SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}
/**
* @brief SysTick 中断服务函数 更新时基
*/
void SysTick_Handler(void)
{
unsigned char i;
for(i=0;i if(Task_Delay[i]) { Task_Delay[i]--; } } }
上一篇:stm32专题三十九:SDIO
史海拾趣
|
遇到 VXworks 下 Intel 82541千兆网卡驱动的问题 在VXWORKS5.5下调试82541的网卡驱动,一开始VXWORKS加载时提示CHECK CAPBLE CONNECTION ! 如何修改了MIILIB.C中的MIIAUTONEGSTART与MIIAUTOPHYINIT函数? 就可以正常启动也可以PING通了,FTP也可以连上,但是无法通过FTP传输文件.请 ...… 查看全部问答> |
|
rom boot loader在wince 5.0的应用问题? 有人实现过rom boot loader吗? 我用的板子是研华的pcm3370 有谁能告知,rom boot loader怎么烧写到开发板上的? 它的程序与硬件相关,怎么改?   ...… 查看全部问答> |
|
请教大家, 泰文中, 由于主导字符是单独的一个字符, 随从字符也是单独的一个字符, 结加后如何显示.使用自造字吗?或者是GB18030字符集已经有了组合后的编码.… 查看全部问答> |
|
新手 spi和一块射频芯片通信 不知道该怎么解决了 希望论坛上的高手能够帮帮忙 1、我的初始化程序 //时钟 CLK_ICKR = (1 << HSIEN);//HSI ENABLE; while((CLK_ICKR & 0X02) == 0);//WAITE FOR HSI STEABLE CLK_CKDIVR = 0X10;//HS ...… 查看全部问答> |




