嵌入式_一种非常简单实用的基于GD32的裸机程序框架

这篇具有很好参考价值的文章主要介绍了嵌入式_一种非常简单实用的基于GD32的裸机程序框架。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

嵌入式_一种非常简单实用的基于GD32的裸机程序框架

搜索了一下关于GD或ST裸机程序的问题,网上有非常多也非常的例子,但是针对裸机开发的程序框架却比较少,这里简单整理了一下在项目中使用过的一种比较小巧便携的裸机程序框架(确切点说算不上框架,只能说一种写法)。



前言

之前常见的裸机程序框架就是流水账框架,比如某个做STM32开发系列教程的****团队,先是一堆初始化,然后一个大while循环,循环里面可以无限添加代码,一个功能一个函数往里加,随着经手的coder越来越多,一行一行往上加,慢慢得就成了屎山代码。我在第一家公司曾经接收手一个七代单传流传下来的祖传代码,一个main函数就有260多行,while循环占了一大半,结构冗余,效率极低。后来花大力气改了框架直接重构。

这个框架基于GD32F103CBT6硬件平台,标准的72MHz系统时钟, 使用标准库GD32F10x_Firmware_Library_V1.0.0此库坑多慎用


一、框架原理

框架大致原理就是使用定时器模拟一个实时操作系统,每1ms产生一个中断并进行累加计数,计数到10、50、100、500、1000时会对相关的标记位置位,表示此时间对应的函数应该执行,在主函数中while(1)循环就是对标记位进行判断并执行对应的任务函数和对标记位进行复位,说白了就是模拟的一个非常简单的μC-OS操作系统,大致原理图如图所示。
嵌入式_一种非常简单实用的基于GD32的裸机程序框架,单片机嵌入式,单片机,stm32,c语言

二、步骤分析

1.定时器中断配置

为了不占用资源,我们选择使用系统自带的滴答定时器,是其产生1ms中断,并且要保证其优先级最高,使其不被其他中断打断。

代码如下(示例):

/**
  * @brief  Configure SysTick.
  * @param  None
  * @retval None
  */
void SysTick_Configuration(void)
{    
    /* Setup SysTick Timer for 108Hz interrupts */
    if (SysTick_Config(SystemCoreClock / 1000)) // 1ms tick
    {
        /* Capture error */
        while (1);
    }
    /* Configure the SysTick handler priority */
    NVIC_SetPriority(SysTick_IRQn, 0x00);
}

2.中断函数

中断函数中,我们使用静态局部变量对中断次数进行累计并判断,在时间性要求不高的情况下,为了保证各个任务可错开,我们进行取模运算来判断是否触发相关任务,如果触发则对标记位数组中的对应位置位。
代码如下(示例):

#define TASKFUNNUMBER  		6
#define TASKMAXCOUNTER		6000

typedef struct
{
	uint16_t Period;
	uint16_t Remainder;
}TaskTimeType;

static uint8_t TaskFlag[TASKFUNNUMBER] = {0, 0, 0, 0, 0, 0};
static TaskTimeType TimeArr[TASKFUNNUMBER] = 
 {
   {10, 2},
   {50, 49},
   {100, 97},
   {500, 497},
   {1000, 999},
   {2000, 1999}
 };
 
void Task_1msNotification(void)
 {
   static uint16_t Counterms = 0;
   uint8_t i = 0;
  
	 if(1msCounter > TASKMAXCOUNTER)
	 {
			1msCounter = 0;
	 }
	 else
	 {
			Counterms ++;

			for(i = 0; i < TASKFUNNUMBER; i++)
			{
				if((Counterms % TimeArr[i].Period) == TimeArr[i].Remainder)
				{
					TaskFlag[i] = TRUE;
				}
			}
	 }
}

3.任务管理函数

轮询判断标记位数组中的各个标记位,如果被置位,则通过函数指针调用相关时间片函数即可。
代码如下(示例):

typedef void (*TaskFunType)(void);

static TaskFunType TaskFunPtr[TASKFUNNUMBER] = 
 {
   &TASK_10msFunc,
   &TASK_50msFunc,
   &TASK_100msFunc,
   &TASK_500msFunc,
   &TASK_1000msFunc
   &TASK_2000msFunc
 };
 
void MainFunction(void)
 {
   uint8_t i = 0;
   
   for(i = 0; i < TASKFUNNUMBER; i++)
   {
     if(TaskFlag[i] == TRUE)
     {
       if(TaskFunPtr[i] != NULL)
       {
         TaskFunPtr[i]();
         TaskFlag[i] = FALSE;
       }
     }
   }
 }

4.主函数

主函数中先对各个模块进行初始化,初始化完成后在while(1)循环中调用上面的MainFunction()函数,轮流调用执行时间片函数,其他各个模块例如LED或串口模块的使用只需要在对应的时间片函数中即可。
代码如下(示例):

int main(void)
{
  SystemInit();
  SysTick_Configuration();
  IO_Init();
  USART0_Init();
  SPI_Init();
  LED_Init();
  Appliction_Init();
  FWDG_Init();
  while(1)
  {
    MainFunction();
  }  
}

void TASK_10msFunc(void)
{
	//Appliction();
}
void TASK_50msFunc(void)
{
	//LED_ManageFunc();
	//SPI_SendManageFunc();
}
void TASK_100msFunc(void)
{
}
void TASK_500msFunc(void)
{	
	//Usart_SendManageFunc();
}
void TASK_1000msFunc(void)
{
	//LED_ManageFunc();
}
void TASK_2000msFunc(void)
{
	//FWDG_FeedWdg();
}

总结

之前在一个项目中使用这种框架,还是比较方便,可以根据各个模块的时间要求选择对应的时间片函数,比如我需要1秒反转一次LED灯,我就直接将反转函数写入1s任务中,不会像“流水账”框架由于某些任务执行时间长短不一而导致我的LED反转时间误差较大,这种框架(确切点说算不上框架)主打就是一个简单便携,如果有什么疑问欢迎留言讨论,有言必回!文章来源地址https://www.toymoban.com/news/detail-543760.html

到了这里,关于嵌入式_一种非常简单实用的基于GD32的裸机程序框架的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 自定义循环队列、软件定时器、事件集,实用嵌入式代码库

    本篇博文分享一个很实用的嵌入式代码库。 它可灵活应用到有无RTOS的程序中,采用C语言面向对象的思路实现各个功能,尽可能最大化的复用代码,目前为止工具包包含: 循环队列、软件定时器、事件集 。 网址:https://download.csdn.net/download/m0_38106923/87765476?spm=1001.2014.3001.550

    2024年02月03日
    浏览(49)
  • 单片机读/写端口或引脚区别及具体1个用例(一种基于STC8G1K08A最小8脚嵌入式单片机LED安全夜灯方案)

    51单片机读引脚和读端口测试总结_单片机怎么读取引脚电平_爱嘟嘟的小屁孩的博客-CSDN博客 近期看了几篇有关单片机读/写端口或引脚的区别的文章,其中上面引用本CSDN的这篇文章,总结的2点感觉还不错,先引用一下: 1. 51单片机里对某一个I/O口进行读--改--写(例如上面的

    2024年02月08日
    浏览(47)
  • ARM简单程序设计【嵌入式系统】

    2023-4-6 20:26:54 以下内容源自《【嵌入式系统】》 仅供学习交流使用 Keil 4 安装教程及简单使用【嵌入式系统】 新建工程xxx 芯片:ARM7 (Little Endian) 设置工程属性 Build结果必须是0Error的 如果是下图看配置是否正确 注意这个: 1.每一次修改代码就需要重写Build 2.READWRITE区变量初始

    2023年04月20日
    浏览(62)
  • 嵌入式软件测试笔记11 | 测试设计技术简单说明

    即分析测试基础,明确每一个测试需要的情形; 例如: 需要测试的情形包含所有的条件,true、false、有效值、无效值等。 测试情形被转换为测试用例; 逻辑测试用例课能就是测试情形; 逻辑测试用例即描述的测试情形的类型,不需要为相关参数赋确定的值就可以被覆盖到

    2024年02月16日
    浏览(44)
  • 【嵌入式学习】网络通信基础-项目篇:简单UDP聊天室

    源码已在GitHub开源:0clock/LearnEmbed-projects/chat 客户端功能: 上线发送登录的用户名[yes] 发送消息和接收消息[yes] quit退出 服务器端功能: 统计用户上线信息,放入链表中[yes] 接收用户信息并给其他用户发送消息[yes] 服务器也支持给所有用户群发消息[yes] 接收下线提醒

    2024年01月25日
    浏览(57)
  • 基于嵌入式的智能台灯系统

    通过微信小程序控制台灯的亮灭及亮度。采集温湿度传到微信小程序上,台灯可以显示实时北京时间。 功能展示 01智能台灯演示 http://www.yoyolife.fun/iot:Mqtt服务器,我是在这里注册的,免费一个,之后每个2块钱每月。主要是结构简单,用起来容易。 下位机即ESP32要选择 mqtt地

    2024年02月02日
    浏览(43)
  • 【嵌入式开源库】MultiButton的使用,简单易用的事件驱动型按键驱动模块

    MultiButton 是一个小巧简单易用的事件驱动型按键驱动模块,可无限量扩展按键,按键事件的回调异步处理方式可以简化你的程序结构,去除冗余的按键处理硬编码,让你的按键业务逻辑更清晰。 本章使用环境: 正点原子stm32F4探索者 代码工程使用正点原子HAL库实验三-按键输

    2024年02月02日
    浏览(51)
  • 嵌入式毕设分享 基于单片机的智能音响设计与实现 -物联网 嵌入式 stm32

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月22日
    浏览(56)
  • 嵌入式毕设分享 基于单片机的风速测量系统 - 物联网 嵌入式 stm32 arduino

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月20日
    浏览(62)
  • 基于IAP的嵌入式系统在线编程设计(学习)

    摘要:为了实现嵌入式系统程序的在线升级,提出一种基于IAP在线编程的程序更新方法。 以STM32L431控制器为例,该方法对控制器的片内FLASH进行区域划分,分别存放引导程序、执行程序及待更新程序。 系统通过运行引导程序将待更新程序更新到执行程序的FLASH区域,程序更新

    2024年02月15日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包