stm32多线程 单片机如何实现多线程

发布者:WanderlustGaze最新更新时间:2024-05-10 来源: elecfans关键字:stm32  多线程  单片机 手机看文章 扫描二维码
随时随地手机看文章

STM 32系列是专门应用在高性能、低成本、低功耗的嵌入式应用设计的ARM Corte-M0,M0+,M3,M4和M7内核,是主流的嵌入式单片机之一。


多线程通常是指从计算机软件或硬件上实现多个线程并发执行的技术,多线程技术有利于提升计算机整体处理性能。

基于STM32单片机的多线程源代码实例1:

#include “Hal_Led/Hal_Led.h”

#include “Hal_delay/delay.h”

#include “Hal_Key/Hal_Key.h”

#include “ringbuffer.h”

#define APP_LED2_BLINK_EVENT 0x0001

#define HAL_LED1_BLINK_EVENT 0x0001

#define TASK_NO_TASK_RUNNING 0xFF

unsigned short Hal_ProcessEvent( unsigned char task_id, unsigned short events );

unsigned short App_ProcessEvent( unsigned char task_id, unsigned short events );

typedef unsigned short uint16;

typedef unsigned char uint8;

#define TASK_CNT 2 //定义线程的个数

//定义函数指针

typedef unsigned short (*pTaskEventHandlerFn)( unsigned char task_id, unsigned short events );

//线程函数表

const pTaskEventHandlerFn tasksArr[] =

{

Hal_ProcessEvent,

App_ProcessEvent

};

const unsigned char tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[ 0] );

//uint16 *tasksEvents;

uint16 tasksEvents[TASK_CNT] = { 0}; //每个线程有16位位域空间用于设置事件

static uint8 activeTaskID = 0xFF; //当前任务ID,指示作用

#define SUCCESS 0x00

#define FAILURE 0x01

#define INVALID_TASK 0x02

uint8 osal_set_event( uint8 task_id, uint16 event_flag )

{

if ( task_id 《 tasksCnt )

{

tasksEvents[task_id] |= event_flag; // Stuff the event bit(s)

return ( SUCCESS );

}

else

{

return ( INVALID_TASK );

}

}

/**

* @brief 程序入口

* @param none

* @return none

*/

int main( void)

{

unsigned short taskID = 0;

uint8 idx = 0;

SystemInit(); //系统时钟初始化

delayInit( 72); //滴答定时器初始化

Led_Init(); //LED初始化

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

osal_set_event( 0, HAL_LED1_BLINK_EVENT);

osal_set_event( 1, APP_LED2_BLINK_EVENT);

while( 1)

{

do

{

if(tasksEvents[idx]) //轮训获知哪个线程有事件需要进行处理

{

break;

}

}

while (++idx 《 tasksCnt);

if (idx 《 tasksCnt)

{

uint16 events;

events = tasksEvents[idx];

tasksEvents[idx] = 0; // 清除事件数组中的事件

activeTaskID = idx;

events = (tasksArr[idx])( idx, events ); //调用线程函数

activeTaskID = TASK_NO_TASK_RUNNING;

tasksEvents[idx] |= events; // 添加未处理的事件到本线程的事件组中

}

delayMs( 1000);

}

}

/**

* @brief 应用层处理

* @param none

* @r

*/

unsigned short Hal_ProcessEvent( unsigned char task_id, unsigned short events )

{

if ( events & HAL_LED1_BLINK_EVENT )

{

Led_Reverse( 1);

return events ^ HAL_LED1_BLINK_EVENT; //清除事件

}

}

/**

* @brief 硬件控制线程

* @param none

* @r

*/

unsigned short App_ProcessEvent( unsigned char task_id, unsigned short events )

{

if ( events & APP_LED2_BLINK_EVENT )

{

Led_Reverse( 2);

return events ^ APP_LED2_BLINK_EVENT; //清除事件

}

基于STM32单片机的多线程源代码实例2:

public class SimpleThread {

//私有的静态成员内部类,实现了Runnable接口

private static class ThreadMessage implements Runnable{

public void run(){

String[] info = {“消息1”,“消息2”, “消息3”, “消息4”};

try {

for(int i=0;i《info.length;i++){

Thread.sleep(4000);

displayThreadMessage(info[i]);

}

} catch (InterruptedException e) {

displayThreadMessage(“不能正常工作”);

}

}

}

//显示消息,消息是当前线程的名字

static void displayThreadMessage(String message){

String threadName = Thread.currentThread().getName();

//格式化输出线程消息

System.out.format(“%s: %s%n”, threadName, message);

}

public static void main(String[] args) throws InterruptedException {

// 中断ThreadMessage线程之前延迟的毫秒数(默认是一分钟)

long delay =1000 * 60;

//如果有命令行参数,那么在命令行参数中给出推迟的时间

if(args.length》0){

try {

delay =Long.parseLong(args[0])*1000;

} catch (NumberFormatException e) {

System.err.println(“参数必须是整数”);

System.exit(1);

}

}

displayThreadMessage(“启动线程ThreadMessage.。。”);

long startTime = System.currentTimeMillis();

Thread t = new Thread(new ThreadMessage());

t.start();

displayThreadMessage(“等待线程ThreadMessage结速。。。”);

//循环直到ThreadMessage线程退出

while(t.isAlive()){

displayThreadMessage(“继续等待线程ThreadMessage.。。”);

//最多等待3秒钟ThreadMessage线程结速

t.join(3000);

//如果线程t运行的时间超过delay指定时间

if(((System.currentTimeMillis() - startTime) 》 delay) && t.isAlive()){

displayThreadMessage(“线程ThreadMessage运行时间太久了,不想等待!”);

t.interrupt();

t.join();

}

}

displayThreadMessage(“结束线程ThreadMessage!!!”);

}

}

基于STM32单片机的多线程源代码实例3:

#include “Hal_Led/Hal_Led.h”

#include “Hal_delay/delay.h”

#include “Hal_Key/Hal_Key.h”

#include “ringbuffer.h”

#define APP_LED2_BLINK_EVENT 0x0001

#define HAL_LED1_BLINK_EVENT 0x0001

#define TASK_NO_TASK_RUNNING 0xFF

unsigned short Hal_ProcessEvent( unsigned char task_id, unsigned short events );

unsigned short App_ProcessEvent( unsigned char task_id, unsigned short events );

typedef unsigned short uint16;

typedef unsigned char uint8;

#define TASK_CNT 2 // 定义线程的个数

// 定义函数指针

typedef unsigned short (*pTaskEventHandlerFn)( unsigned char task_id, unsigned short events );

// 线程函数表

const pTaskEventHandlerFn tasksArr[] =

{

Hal_ProcessEvent,

App_ProcessEvent

};

const unsigned char tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );

//uint16 *tasksEvents;

uint16 tasksEvents[TASK_CNT] = {0}; // 每个线程有 16 位位域空间用于设置事件

staTIc uint8 acTIveTaskID = 0xFF; // 当前任务 ID,指示作用

#define SUCCESS 0x00

#define FAILURE 0x01

#define INVALID_TASK 0x02

uint8 osal_set_event( uint8 task_id, uint16 event_flag )

{

if ( task_id 《 tasksCnt )

{

tasksEvents[task_id] |= event_flag; // Stuff the event bit(s)

return ( SUCCESS );

}

else

{

return ( INVALID_TASK );

}

}

/**

* @brief 程序入口

* @param none

* @return none

*/

int main(void)

{

unsigned short taskID = 0;

uint8 idx = 0;

SystemInit(); // 系统时钟初始化

delayInit(72); // 滴答定时器初始化

Led_Init(); //LED 初始化

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

osal_set_event(0, HAL_LED1_BLINK_EVENT);

osal_set_event(1, APP_LED2_BLINK_EVENT);

while(1)

{

do

{

if(tasksEvents[idx]) // 轮训获知哪个线程有事件需要进行处理

{

break;

}

}

while (++idx 《 tasksCnt);

if (idx 《 tasksCnt)

{

uint16 events;

events = tasksEvents[idx];

tasksEvents[idx] = 0; // 清除事件数组中的事件

acTIveTaskID = idx;

events = (tasksArr[idx])( idx, events ); // 调用线程函数

activeTaskID = TASK_NO_TASK_RUNNING;

tasksEvents[idx] |= events; // 添加未处理的事件到本线程的事件组中

}

delayMs(1000);

}

}

/**

* @brief 应用层处理

* @param none

* @r

*/

unsigned short Hal_ProcessEvent( unsigned char task_id, unsigned short events )

{

if ( events & HAL_LED1_BLINK_EVENT )

{

Led_Reverse(1);

return events ^ HAL_LED1_BLINK_EVENT; // 清除事件

}

}

/**

* @brief 硬件控制线程

* @param none

* @r

*/

unsigned short App_ProcessEvent( unsigned char task_id, unsigned short events )

{

if ( events & APP_LED2_BLINK_EVENT )

{

Led_Reverse(2);

return events ^ APP_LED2_BLINK_EVENT; // 清除事件

以上是关于STM32单片机的源代码,希望对用户有所帮助。


关键字:stm32  多线程  单片机 引用地址:stm32多线程 单片机如何实现多线程

上一篇:STM32F0单片机如何用一个GPIO引脚来触发中断
下一篇:关于STM32CubeIDE环境下的变量显示及监测

推荐阅读最新更新时间:2024-11-11 15:33

揭秘STM32多路电压测量电路 —电路图天天读(62)
   数据采集技术是信息科学的重要分支之一,数据采集也是从一个或多个信号获取对象信息的过程。数据采集是工业控制等系统中的重要环节,通常采用一些功能相对独立的单片机系统来实现,作为测控系统不可缺少的部分,数据采集的性能特点直接影响到整个系统。电压的测量最为普遍性,研究设计并提高电压测量精度的方法及仪器具有十分重要的意义。在电压测量设计中,单片机作为控制器,是整个设计的核心。除此之外,设计中还必须有模数转换器(ADC)。ADC用于直接采集模拟电压并将模拟信号转换成数字信号,它直接影响着数据采集的精度和速度。   ADC控制电路模块   STM32的数字/模拟转换模块(DAC)是12位数字输入,电压输出的数字/模拟转换器。本设计中使
[单片机]
揭秘<font color='red'>STM32</font>多路电压测量电路 —电路图天天读(62)
传感器与AT89S52单片机的接口电路设计:测量模块电路
该测试仪以AT89S52单片机为核心,外接温湿度传感器SHTll、照度传感器TSL2561、四位共阴数码管、RS485总线通信接口以及显示切换按键。单片机上电工作后,对当前温度、湿度、光强度进行实时测量,通过按键切换将测得的3种参数通过LED数码管进行轮流显示;此外,还可以通过RS485总线与PC机进行通信,将参数值传送到上位机,以达到远程监测的目的。该测试仪的结构框图如图1所示。 测量模块电路 温度和湿度测量采用的是瑞士Sensirion公司生产的SHTll传感器。该传感器采用独特的CMOsens TM技术,将温湿度传感器、信号放大处理、A/D转换、I2C总线全部集成在一块芯片上,可直接与单片机接口。该芯片采用数字式
[单片机]
传感器与AT89S52<font color='red'>单片机</font>的接口电路设计:测量模块电路
CubeMX配置stm32的DAC
我们使用 STM32CubeMX 软件进行配置。DAC 的配置是相对很简单的,如下图所示: 选择两个输出通道,其中 External Trigger 选项为是否选择 外部中断EXTI9 触发,如下图所示: DAC 的基本设置,很简单,对于博主使用的 STM32L151 来说就只有2个选项: DAC选择了输出缓存,可以用来减少输出阻抗,无需外部运放即可直接驱动外部负载。但是输出的电压没法低于20mv。 不使能输出缓存,DAC可以输出低于20mv的信号。 对于其他型号的 DAC ,可能还会有下面两个选项: Wave generation mode 波形生成模式:可选三角波发生器 ( Triangle wave genera
[单片机]
CubeMX配置<font color='red'>stm32</font>的DAC
关于stm32中串口重定向问题详解
usart这部分代码我也是从网上copy出来的,一下是作者的解释: 简单地说:想在mdk 中用printf,需要同时重定义fputc函数和避免使用semihosting(半主机模式), 标准库函数的默认输出设备是显示器,要实现在串口或LCD输出,必须重定义标准库函数里调用的与输出设备相关的函数. 例如:printf输出到串口,需要将fputc里面的输出指向串口(重定向),方法如下: #ifdef __GNUC__ /* With GCC/RAISONANCE, small printf (option LD Linker- Libraries- Small printf set to 'Yes') calls
[单片机]
51单片机多机通信原理
一、多机通信原理 在多机通信中,主机必须要能对各个从机进行识别,在51系列单片机中可以通过SCON寄存器的SM2位来实现。当串口以方式2或方式3发送数据时,每一帧信息都是11位,第9位是数据可编程位,通过给TB8置1或置0来区别地址帧和数据帧,当该位为1时,发送地址帧;该位为0时,发送数据帧。 在多机通信过程中,主机先发送某一从机的地址,等待从机的应答,所有的从机接收到地址帧后与本机地址进行比较,若相同,则将SM2置0准备接收数据;若不同,则丢弃当前数据,SM2位不变。 二、多机通信电路图 此处,U1作为主机,U2为从机1,U3为从机2。 三、C语言程序 (1)主机程序 #include#include #define
[单片机]
51<font color='red'>单片机</font>多机通信原理
PIC单片机之ICSP
今次要说的是ICSP。ICSP,全称In-Circuit Serial Programming,在线串行编程。这行英文和ICSP这四个字母,一般使用时都带有TM标记的,也就是说,这是MICROCHIP的商标。也是MC独有的吧。呵呵。 从名字可以看出来,ICSP是一种编程方法,也就是说是一种烧写手段。这种手段可以在线烧写 即不需要将芯片取下就可以在板子上烧写。而这种烧写方法使用串行的数据。在线烧写其实也不是什么新闻了,大家熟悉的TI的DSP,一向可以使用JTAG口进行烧写,那就是标准的在线烧写。 MC的ICSP,使用起来极为方便,应用ICSP进行烧写,只需要使用芯片上的5个脚就可以,其中包括VDD VSS,这两个电源一定要供上。然后
[单片机]
调试STM8/stm32串口时发现的问题
描述:串口中断1用来接收到的数据,我是用串口助手发送一个8字节的数据,然后我想查看8个字节是否被单片接收,比如数据是0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08这8个数值,串口中断 #pragma vector=ITC_IRQ_UART1_RX + 2 __interrupt void Uart1RxdInt(void) { //此函数内已完成清中断标志 u8 ret; if(UART1_GetFlagStatus(UART1_FLAG_RXNE)!=RESET) { tmp = UART1_ReceiveData8(); ret=UAR
[单片机]
STM32系列是大端还是小端?
ARM的手册上有关于大小端的描述,如下: The processor can access data words in memory in little-endian format or big-endian format. It always accesses code in little-endian format. Note: Little-endian is the default memory format for ARM processors. STM32是固定配置为小端的 The bytes are coded in memory in Little Endian format. The lowest number
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved