以OLED为例介绍RTOS面向对象编程

本文以屏幕显示为例,详细介绍了RTOS嵌入式系统框架。包括嵌入式系统的拆分原则,面向对象编程基础,以及如何设计显示系统,并探讨了FreeRTOS在多任务间的通讯方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

小白能懂:嵌入式进阶:RTOS嵌入式系统框架

第一章 嵌入式常用裸机编程框架
第二章 面向对象编程基础
第三章 ESP8622物联网基础
第四章 STM32与ESP8266物联网编程
第五章 物联网编程优化
第六章 以OLED为例介绍RTOS面向对象编程


本节与本系列第二章联系较为紧密,建议一起观看


前言

学习韦东山老师的七天物联网实战及直播课相关内容,以其课程笔记为骨,记录一下学习的过程,可能会加入一些自己的感想。
最后欢迎点赞、收藏与评论交流!


一、拆分系统

1 系统拆分原则

各系统尽可能独立,不互相干涉。

2 按照数据流向分:输入/输出/业务

2.1 输入部分

输入部分主要是系统的输入,主要包括用户输入(键盘、串口或者其他按键)、传感器(接收到外界的数据)及远城操控(PC及电脑上位机端)等等。
在这里插入图片描述

2.1 输出部分

输出部分主要有显示系统(显示屏或者led灯)、控制各类设备(电机或者其他的执行机构)及数据保存(flash芯片)等。
在这里插入图片描述

2.3 业务部分

业务系统主要是指输入输出系统之间的关系。
在这里插入图片描述
复杂的业务系统示例如下所示:
在这里插入图片描述

3 以LCD为例设计业务系统

原则:驱动只提供功能,不提供策略。 各司其职,互不干涉。

问题:如何设计一个程序在LCD屏幕上显示一个字符“A”,难点在于

  • LCD的接口可能有I2C、SPI或者其他的ram读写
  • A可能多种字体,或者其他的艺术字的格式?还有字体大小的不同

3.1 显示系统分层 ——设备层

  1. LCD自带显存的设备,RAM接口
    在这里插入图片描述
    给定基地址baseaddr,只要写入之后,硬件会帮忙自动刷新图像。

  2. LCD自带显存的设备,I2C、SPI接口
    在这里插入图片描述最左端为人为分配的内存,与显存大小相同,通过手动刷新的方式来显示图像。

  3. 计算能力强大的linux芯片,有LCD控制器,相当于芯片内部开辟了一段内存充当LCD显存。(LCD无显存,接口RAM)
    在这里插入图片描述
    给定基地址baseaddr,写入之后,显存的图像内容会被自动刷新。

3.2 显示系统分层 ——结构体

设计一款显示系统,可以支持上述1,2,3种屏幕要求,为此我们设计结构体如下所示:

DisplayDev{
char *name;
int iXres;
int iYres;
int iBpp; //(bit per prex)每个像素多少个字节显示
char *FrameBuffer; //基地址
void (*FlashFB)(); //刷显存的子函数,只在第二种屏幕中有需要;第1、3中屏幕中无需该函数
}

3.3 显示系统分层 ——显示设备框架

在这里插入图片描述
程序框架主要有以下方面的分层:设备层(APP),管理层和驱动层。
各层程序之间层次分明,不互相干涉。设备层主要是进行后续的算法或上层开发;管理层主要是对底层驱动的控制,控制哪些驱动可以供上层程序使用;驱动层主要是对硬件的控制与编写,只是写硬件芯片上的驱动。

伪代码程序编写如下:

1. 首先构建framebuffer_manager的结构体,

<framebuffer_manager.h>

typedef struct DisplayDev {
	char *name;    
	int iXres;
	int iYres;
	int iBpp;
	char *Framebuffer;
    void (*Init)(struct DisplayDev *d);
    void (*FlushFB)(struct DisplayDev *d);
}DisplayDev, *p_DisplayDev;

2. 驱动层相应的初始化函数

<oled.c>

static void oled_init(DisplayDev *dev)
{
}

static void oled_flush(DisplayDev *dev)
{
}

static char oled_fb[1024];

static DisplayDev oled = {
	"oled",
	128,   //屏幕尺寸128*64
	64,
	1,     //数组中每一个字节代表一个像素点
	oled_fb,     //基地址
	oled_init,
	oled_flush,
};

void oled_init(void)
{
	register_display_dev(&oled);       //注册函数的实现,将底层的驱动交给上层应用程序
}

3. 实现注册函数

int dev_cnt = 0;
DisplayDev *devs[32];

void register_display_dev(DisplayDev *dev)
{
	devs[dev_cnt] = dev;
	dev_cnt++;
}

void desplay_devs_init(void)
{
	oled_init();
}

DisplayDev *get_display_dev(char *name)
{
	int i = 0; 
	for (i = 0; i < dev_cnt; i++)
		if (strcmp(name, devs[i]->name) == 0)
			return devs[i];

	return NULL;
}

4. 在main函数中编写测试程序

void main(void)
{
	DisplayDev *pdev;
	int size;
	
	desplay_devs_init();                //先初始化屏幕

	pdev = get_display_dev("oled");        //以名字取出相应的屏幕

	pdev->Init(pdev);                     //初始化这个屏幕

	size = pdev->iXres * pdev->iYres * pdev->iBpp / 8;    //计算屏幕尺寸
	memset(pdev->Framebuffer, 0, size);        //初始化屏幕都为0

	pdev->FlushFB(pdev);              //开始刷新屏幕
}

3.4 显示系统分层 ——显示系统

在上一节3.3中主要对硬件设备的驱动框架进行了介绍,本节主要对屏幕的具体显示系统(如某个像素点的显示,文字的显示,显示字符串,或者位图)进行介绍:
在这里插入图片描述

/* color: 0x00RRGGBB */
int SetPixel(DisplayDev *pdev, int x, int y, int color)
{
	char *base = pdev->Framebuffer;                       //基地址
	int offset = (y*(pdev->iXres)+x)*pdev->iBpp/8;        //要操作的像素点需要偏移的字节数,将一维数据转化为二维数据
	char *data;                                           
	char *dataw;
	int bit = x % 8;

	data = &base[offset];
	dataw = &base[offset]; 

	switch (pdev->iBpp)
	{
		case 1:
		{
			if (color)
				data |= (1<<bit);                   //对特殊的字节进行操作,到底是点亮还是熄灭              
			else
				data &= ~(1<<bit);
			
			break;
		}

		case 8:
		{
			*data = color;                          //对特殊的字节进行操作,显示特殊的颜色 
			break;
		}

		case 16:
		{
			*dataw = color;
			break;
		}
	}
}

现在的程序分层如下所示:
在这里插入图片描述

二、freertos操作

有以下问题,一个小人在oled屏幕上一直走,单片机有一个无中断功能的按键去停止他,如何实现该功能?
在这里插入图片描述

2.1 裸机思维

使用定时器去实现小人的一直运动,在运动任务之前去查询一下按键,如果按键按下,就去停止小人。
在这里插入图片描述

2.2 freertos框架

freertos主要解决多个耗时程序之间的时间分配问题!
在这里插入图片描述
在这里插入图片描述
现在的难点主要是主要是多任务之间的通讯,任务2需要任务1的通知来停止小人的运动。
在RTOS中一般不用全局变量,一般是队列和信号量进行通讯功能。

在这里插入图片描述

2.3 多进程与多线程

以下属于扩展内容,他们的主要区别是:一个进程可以包含多个线程,同一个进程拥有的全局变量可以在进程中的不同线程使用。如对以下图片有疑问,请移步评论区讨论:
在这里插入图片描述

总结

本文主要以屏幕显示为例介绍了多任务系统的程序框架。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值