STM8驱动HC-05蓝牙模块
使用软件:IAR FOR STM8 编程方式:固件库 硬件配套:STM8S105C6T6实验板 1 配置蓝牙 使用 USB-TTL 模块与 HC-05 蓝牙模块连接(左为 USB 转 TTL,右为蓝牙模块): 3V3–>VCC TXD–>RXD RXD–>TXD GND–>GND 按下蓝牙模块的黑色小按钮的同时,连上电脑,这时蓝牙模块上的信号灯闪烁模式为 2s 的长闪烁,说明蓝牙进入 AT 模式,可以向它发送 AT 指令了。接着打开串口调试助手,波特率选择 38400,其他设置不用变。然后发送 AT 指令,每条指令发送成功后,调试助手会收到 OK 的信息。 部分 AT 指令如下(均以回车、换行结尾): 123456AT+NAME=Bluetooth-Mount256 // 蓝牙名称为Bluetooth-Mount256AT+ROLE=0 // 蓝牙模式为从模式AT+CMODE=0 // 蓝牙连接模式为任意地址连接模式AT+PSWD="1234" ...
uCOS-III 学习记录(11)——任务管理
参考内容:《[野火]uCOS-III内核实现与应用开发实战指南——基于STM32》第 15、16 和 21 章。 从本文开始,是 uCOS 的 API 应用。 1 任务状态 在 uCOS 中,任务状态分为以下几种,任务就是在这几种状态中来回变化的: 就绪(OS_TASK_STATE_RDY):该任务在就绪列表中,就绪的任务已经具备执行的能力,只等待调度器进行调度,新创建的任务会初始化为就绪态。 延时(OS_TASK_STATE_DLY):该任务处于延时调度状态。 等待(OS_TASK_STATE_PEND):任务调用 OSQPend()、OSSemPend() 这类等待函数,系统就会设置一个超时时间让该任务处于等待状态,如果超时时间设置为 0,任务的状态,无限期等下去,直到事件发生。如果超时时间为 N(N>0),在 N 个时间内任务等待的事件或信号都没发生,就退出等待状态转为就绪状态。(现阶段忽视) 运行(OS_TASK_STATE_PEND_TIMEOUT):该状态表明任务正在执行,此时它占用处理器,uCOS 调度器选择运行的永远是处于最高优先级的就绪态任务,当任务被运...
uCOS-III 学习记录(10)——时间片轮转调度
参考内容:《[野火]uCOS-III内核实现与应用开发实战指南——基于STM32》第 14 章。 0 时间片轮转调度的意义 我们现在实现的 uCOS 内核,包含了就绪列表和时基列表。就绪列表的插入规则与优先级有关,而时基列表的插入规则与时基计数器和延时时间有关。上一篇文章中,已经实现了时基列表的任务调度。但是我们写的内核还有一些缺陷,当不进行任务调度时(注意:任务调度的实质是切换到高优先级的任务去执行),系统只能执行就绪列表下的双向链表头指针对应的任务,那么相同优先级的其他任务就执行不到了。因此,我们希望相同优先级的多个任务都可以执行到,其中一个办法就是每隔一段时间就切换到相同优先级上的任务,这样这些任务都有机会被运行到。 时间片轮转调度用于解决相同优先级下多个任务的运行问题。现在假设 A 优先级下有任务 1、任务 2、任务 3,B 优先级有任务 4 且被阻塞 6 个时间片的长度,所以现在要运行 A 优先级下的任务。 如果不实现时间片轮转,那么 A 优先级排在最前面的任务 1 将运行 6 个时间片,即独占了这 6 个时间片。 如果实现时间片轮转,那么 A 优先级下的任务可以商量...
uCOS-III 学习记录(9)——时基列表
参考内容:《[野火]uCOS-III内核实现与应用开发实战指南——基于STM32》第 13 章。 1 数据类型定义和宏定义 1.1 时基列表相关宏定义和全局变量(os_cfg_app.h/c & os.h) 在 os_cfg_app.h 中,宏定义时基列表的大小,其推荐值为任务数/4,推荐使用质数,不推荐使用偶数。如果算出来的大小是偶数,则需加 1 变成质数。 12/* 时基列表大小 */#define OS_CFG_TICK_WHEEL_SIZE 17u 接下来在 os_cfg_app.c 中,定义两个全局变量,分别是时基列表(数组)和时基列表的大小。注意需要在 os.h 中声明。 12OS_TICK_SPOKE OSCfg_TickWheel[OS_CFG_TICK_WHEEL_SIZE]; /* 时基列表 */OS_OBJ_QTY const OSCfg_TickWheelSize = (OS_OBJ_QTY)OS_CFG_TICK_WHEEL_SIZE; /* 时基列表大小 */ 在 os.h 中定义 32 位的 Tick 计数器,即 SysTick 周期...
uCOS-III 学习记录(8)——支持多优先级
参考内容:《[野火]uCOS-III内核实现与应用开发实战指南——基于STM32》第 12 章。 本篇内容主要是对过往函数的一些修改,因此,一些细节将不会赘述。 0 数据类型定义和宏定义 0.1 临界段宏定义(os.h) 1234#define OS_CRITICAL_ENTER() CPU_CRITICAL_ENTER()#define OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT()#define OS_CRITICAL_EXIT() CPU_CRITICAL_EXIT()#define OS_CRITICAL_EXIT_NO_SCHED() CPU_CRITICAL_EXIT() 0.2 任务控制块 TCB 定义(os.h) 类型定义: 12345678910111213141516/*----------------------TCB---------------------------*//* TCB 重命名为大写字母格式 */typed...
uCOS-III 学习记录(7)——就序列表
参考内容:《[野火]uCOS-III内核实现与应用开发实战指南——基于STM32》第 11 章。 1 就绪列表和任务控制块的定义(os.h) 1.1 任务控制块链表 OS_TCB 在定义就绪列表之前,先修改一下 TCB 的内容。 TCB 是一条双向链表,每个节点都包含以下内容: 任务栈指针 StkPtr; 任务栈大小 StkSize; 任务阻塞时长 TaskDelayTicks; 任务的优先级 Prio; 前向指针域 PrevPtr 和后向指针域 NextPtr。 12345678910111213141516/*----------------------TCB---------------------------*//* TCB 重命名为大写字母格式 */typedef struct os_tcb OS_TCB;/* TCB 数据类型声明 */struct os_tcb{ CPU_STK *StkPtr; CPU_STK_SIZE StkSize; OS_TICK TaskDelayTicks; /* 任务延时多少个 Ticks,注意 1 个 Tic...
uCOS-III 学习记录(6)——优先级表
参考内容:《[野火]uCOS-III内核实现与应用开发实战指南——基于STM32》第 11 章。 1 优先级表的定义 OSPrioTbl(os_prio.c) 在文件 os_prio.c 中定义优先级表,它是一个数组: 1CPU_DATA OSPrioTbl[OS_PRIO_TBL_SIZE]; /* 定义优先级表 */ 接下来着重理解 CPU_DATA 和 OS_PRIO_TBL_SIZE 的含义。 1.1 CPU_DATA——一个数组元素的数据长度为多少?(cpu.h) 在 cpu.h 中定义了 CPU_DATA 的类型为 unsigned int,也就是一个数组元素为 32 位: 123typedef unsigned int CPU_INT32U;typedef CPU_INT32U CPU_DATA; 如果 MCU 的(字长)类型是 16 位、8 位或者 64 位,只需要把优先级表的数据类型 CPU_DATA 改成相应的位数即可。 1.2 OS_PRIO_TBL_SIZE——数组有多大?(os.h) 这个问题将会关系到优先级表有多大。在 os.h 中宏定...
uCOS-III 学习记录(5)——临界段
参考内容:《[野火]uCOS-III内核实现与应用开发实战指南——基于STM32》第 10 章。 1 临界段 临界段,又叫做临界区。对于多线程而言,它是一段不可分割、不可上下文切换的代码。对于 uCOS 而言,它是一段不可被中断的代码。临界段是不能被中断的,需要关中断或锁调度器(OSSched)以保护临界段。 什么情况下临界段代码会被打断?由刚才的描述可知,临界段被打断有两种情况: 外部中断。 系统调度。在系统调度中会产生 PendSV 异常中断,最终也可以归结为中断。 因此,对临界段保护的实质就是控制中断的开启和关闭。 uCOS 定义了进入临界段的宏和退出临界段的宏,这两个宏分别实现了中断的开启和关闭。 OS_CRITICAL_ENTER() 或 CPU_CRITICAL_ENTER() OS_CRITICAL_EXIT() 或 CPU_CRITICAL_EXIT() 还有一个宏,用于存储中断的状态: CPU_SR_ALLOC() 2 临界段的保护 2.1 Cortex-M 内核的中断指令 在 CM 内核中,中断是通过 CPS 指令来控制的。 1234CPSID I...
uCOS-III 学习记录(4)——时间戳
参考内容:《[野火]uCOS-III内核实现与应用开发实战指南——基于STM32》第 9 章。 1 时间戳 在 uCOS 中,如果要测量一段代码 A 的时间,那么可以在代码段 A 运行前记录一个时间点 TimeStart,在代码段 A 运行完记录一个时间点 TimeEnd,那么代码段 A 的运行时间 TimeUse 就等于 TimeEnd 减去 TimeStart。这里面的两个时间点 TimeEnd 和 TimeStart,就叫作时间戳(Timestamp,简称ts),时间戳实际上就是一个时间点。 比如,在下面的代码中,在需要开始测量的地方调用OS_TS_GET(),在需要结束测量的地方再次调用OS_TS_GET(),则两次调用之间的代码即为被测量的时间长度。 1234TimeStart = OS_TS_GET();OSTimeDly (20); TimeEnd = OS_TS_GET();TimeUse = TimeEnd - TimeStart; 如果 Tick = 10ms,那么 TimeUse 测量到的是 200ms。 现在的问题是:如何实现时间戳呢?DWT 要出场了。 ...
uCOS-III 学习记录(2)——任务时间片运行
参考内容:《[野火]uCOS-III内核实现与应用开发实战指南——基于STM32》第 7 章。 这章的内容是:每隔一定的时间间隔,就会进行一次任务切换,使每个任务都能均等享有 CPU 控制权,这种不停地上下文切换的过程,有点像多进程。同是任务切换,与第一篇笔记不同的是:第一篇笔记是任务自己主动切换,这篇是 SysTick 发起的切换。 1 初始化 SysTick 1.1 SysTick 初始化函数 OS_CPU_SysTickInit (os_cpu_c.c) 由于 SysTick 属于内核外设,所以在 os_cpu_c.c 中定义该函数。实现方法其实很简单,就是我们之前在 STM32 所学的 SysTick 那样进行初始化。 其中函数参数为 ms,意思是经过多少 ms 后触发 SysTick 中断。之后在中断程序内,进行任务切换即可。 123456789101112131415/* 初始化SysTick */void OS_CPU_SysTickInit (CPU_INT32U ms){ SysTick->LOAD = ms * SystemCoreCloc...



