【国民技术N32G430】4、做一个简单好用的多任务调度系统 https://bbs.eeworld.com.cn/thread-1217018-1-1.html
在上面建立任务的前提下,驱动ssd1306,再增加一个任务,用来刷新显示:
1、先定义I2CIO为 SCL----PB6,SDA---PB7,用宏定义相关函数:
//-----------------OLED端口定义----------------
#define I2Cx_SCL_PIN GPIO_PIN_6
#define I2Cx_SCL_GPIO_PORT GPIOB
#define I2Cx_SCL_GPIO_CLK RCC_AHB_PERIPH_GPIOB
#define I2Cx_SDA_PIN GPIO_PIN_7
#define I2Cx_SDA_GPIO_PORT GPIOB
#define I2Cx_SDA_GPIO_CLK RCC_AHB_PERIPH_GPIOB
#define OLED_SCL_Clr() GPIO_Pins_Reset(I2Cx_SCL_GPIO_PORT ,I2Cx_SCL_PIN)
#define OLED_SCL_Set() GPIO_Pins_Set(I2Cx_SCL_GPIO_PORT ,I2Cx_SCL_PIN)//SCL
#define OLED_SDA_Clr() GPIO_Pins_Reset(I2Cx_SDA_GPIO_PORT,I2Cx_SDA_PIN)
#define OLED_SDA_Set() GPIO_Pins_Set(I2Cx_SDA_GPIO_PORT,I2Cx_SDA_PIN)//SDA
#define OLED_CMD 0 //写命令
#define OLED_DATA 1 //写数据
2、定义几个i2c的功能函数如下START、ACK、NACK、STOP、SEND_BYTE函数:
void IIC_delay(void)
{
u8 t=3;
while(t--);
}
//起始信号
void I2C_Start(void)
{
OLED_SDA_Set();
OLED_SCL_Set();
IIC_delay();
OLED_SDA_Clr();
IIC_delay();
OLED_SCL_Clr();
IIC_delay();
}
//结束信号
void I2C_Stop(void)
{
OLED_SDA_Clr();
OLED_SCL_Set();
IIC_delay();
OLED_SDA_Set();
}
//等待信号响应
void I2C_WaitAck(void) //测数据信号的电平
{
OLED_SDA_Set();
IIC_delay();
OLED_SCL_Set();
IIC_delay();
OLED_SCL_Clr();
IIC_delay();
}
//写入一个字节
void Send_Byte(u8 dat)
{
u8 i;
for(i=0;i<8;i++)
{
OLED_SCL_Clr();//将时钟信号设置为低电平
if(dat&0x80)//将dat的8位从最高位依次写入
{
OLED_SDA_Set();
}
else
{
OLED_SDA_Clr();
}
IIC_delay();
OLED_SCL_Set();//将时钟信号设置为高电平
IIC_delay();
OLED_SCL_Clr();//将时钟信号设置为低电平
dat<<=1;
}
}
//发送一个字节
//向SSD1306写入一个字节。
//mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 mode)
{
I2C_Start();
Send_Byte(0x78);
I2C_WaitAck();
if(mode){Send_Byte(0x40);}
else{Send_Byte(0x00);}
I2C_WaitAck();
Send_Byte(dat);
I2C_WaitAck();
I2C_Stop();
}
其他的相关函数我把几个相当的文件上传附件。
3、在main.c中先初始化OLED,然后绘制开始画面,后面添加一个显示的任务,用于刷新数据,做到显示与数据分离:
#include "main.h"
#include "task.h"
#include "oled.h"
u16 task1_id,task2_id,task3_id;
u16 num1,num2;
char str_num1[20], str_num2[20];
//任务1
void task1()
{
num1 +=1;
printf("hellow task1 num:%d\r\n",num1);
sprintf(str_num1,"task1 num:%d",num1);
if(num1>20)
task_delete(task1_id);
}
//任务2
void task2()
{
num2 += 2;
printf("hellow task2 num2:%d\r\n",num2);
sprintf(str_num2,"task2 num:%d",num2);
if(num2>30)
task_delete(task2_id);
}
//显示任务
void task3(void)
{
// OLED_Clear();
OLED_ShowString(8,0,"N32G430",24,1);//12*24 “N32G430”
OLED_ShowString(0,24,str_num1,16,1);
OLED_ShowString(0,40,str_num2,16,1);
OLED_Refresh();
}
/**
*\*\brief Main program
**/
int main(void)
{
log_init();
time6_init();
task_init();
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示
OLED_Refresh();
OLED_ShowString(8,0,"N32G430",24,1);//12*24 “N32G430”
OLED_ShowChinese(0,32,4,32,1); //32*32 国
OLED_ShowChinese(32,32,5,32,1); //32*32 民
OLED_ShowChinese(64,32,6,32,1); //32*32 技
OLED_ShowChinese(96,32,7,32,1); //32*32 术
num1 = num2 = 0;
task1_id = task_create(1000,1000,task1); //创建任务1
task2_id = task_create(1000,1000,task2); //创建任务2
task3_id = task_create(10,10,task3); //创建任务3
OLED_Refresh();
SysTick_Delay_Ms(1000);
OLED_Clear();
while(1)
{
task_handler();
}
}
【总结】多任务系统能把各个任务分解,做到模块化。操作起来相对来说比较方便。相对于FreeRTos又相对于简单,占用内存资源少。
附件没有上传成功,今天出差了,回去把OLED的驱动上传。
软件IIC移植起来就是方便!
引用: 秦天qintian0303 发表于 2022-9-8 17:18 主要是速度还不比硬件的慢,这是最气人的
IIC主要就是搞低速的,SPI硬件就比软件的快了。