STM32学习之:事件标志组

发布者:mancozc最新更新时间:2018-10-21 来源: eefocus关键字:STM32  事件标志组 手机看文章 扫描二维码
随时随地手机看文章

为什么要使用事件标志

事件标志组是实现多任务同步的有效机制之一。也许有不理解的初学者会问采用事件标志组多麻烦,

搞个全局变量不是更简单?其实不然,在裸机编程时,使用全局变量的确比较方便,但是在加上 RTOS 后

就是另一种情况了。 使用全局变量相比事件标志组主要有如下三个问题:

 使用事件标志组可以让 RTOS 内核有效地管理任务,而全局变量是无法做到的,任务的超时等机制需

要用户自己去实现。

 使用了全局变量就要防止多任务的访问冲突,而使用事件标志组则处理好了这个问题,用户无需担心。

 使用事件标志组可以有效地解决中断服务程序和任务之间的同步问题。 

FreeRTOS 任务间事件标志组的实现

任务间事件标志组的实现是指各个任务之间使用事件标志组实现任务的通信或者同步机制。

下面我们来说说 FreeRTOS 中事件标志的实现,根据用户在 FreeRTOSConfig.h 文件中的配置:

 #define configUSE_16_BIT_TICKS 1

配置宏定义 configUSE_16_BIT_TICKS 为 1 时,每创建一个事件标志组,用户可以使用的事件标志是

8 个。

 #define configUSE_16_BIT_TICKS 0 

配置宏定义 configUSE_16_BIT_TICKS 为 0 时,每创建一个事件标志组,用户可以使用的事件标志是24 个。 

上面说的 8 个和 24 个事件标志应该怎么理解呢?其实就是定义了一个 16 位变量,仅使用了低 8bit

或者定义了一个 32 位变量,仅使用了低 24bit。每一个 bit 用 0 和 1 两种状态来代表事件标志。 反映到

FreeRTOS 上就是将事件标志存储到了 EventBits_t 类型的变量中, 这个变量又是怎么回事呢?定义如下: 

由上面定义可以看出,TickType_t 数据类型可以是 16 位数或者 32 位数,这样就跟上面刚刚说的

configUSE_16_BIT_TICKS 宏定义呼应上了。教程配套的例子都是配置宏定义 configUSE_16_BIT_TICKS

为 0, 即用户每创建一个事件标志组, 有 24 个标志可以设置。 如下图所示,这里仅使用 bit0, bit1 和 bit2。 


 下面我们通过如下的框图来说明一下 FreeRTOS 事件标志的实现,让大家有一个形象的认识。 

FreeRTOS 中断方式事件标志组的实现

FreeRTOS 中断方式事件标志组的实现是指中断函数和 FreeRTOS 任务之间使用事件标志。 下面我们

通过如下的框图来说明一下 FreeRTOS 事件标志的实现,让大家有一个形象的认识。

 任务 Task1 运行过程中调用函数 xEventGroupWaitBits,等待事件标志位被设置,任务 Task1 由运

行态进入到阻塞态。

 Task1 阻塞的情况下,串口接收到数据进入到了串口中断服务程序,在串口中断服务程序中设置 Task1

等待的事件标志,任务 Task1 由阻塞态进入到就绪态,在调度器的作用下由就绪态又进入到运行态。

上面就是一个简单的 FreeRTOS 中断方式事件标志通信过程。 实际应用中,中断方式的消息机制要注意以

下四个问题:

 中断函数的执行时间越短越好,防止其它低于这个中断优先级的异常不能得到及时响应。

 实际应用中,建议不要在中断中实现消息处理,用户可以在中断服务程序里面发送消息通知任务,在

任务中实现消息处理,这样可以有效地保证中断服务程序的实时响应。同时此任务也需要设置为高优

先级,以便退出中断函数后任务可以得到及时执行。

 中断服务程序中一定要调用专用于中断的事件标志设置函数,即以 FromISR 结尾的函数。

 在操作系统中实现中断服务程序与裸机编程的区别。

 如果 FreeRTOS 工程的中断函数中没有调用 FreeRTOS 的事件标志组 API 函数,与裸机编程是

一样的。

 如果 FreeRTOS 工程的中断函数中调用了 FreeRTOS 的事件标志组的 API 函数,退出的时候要

检测是否有高优先级任务就绪,如果有就绪的,需要在退出中断后进行任务切换,这点跟裸机编

程稍有区别,详见 实验例程说明(中断方式):

 另外强烈推荐用户将 Cortex-M3 内核的 STM32F103 和 Cortex-M4 内核的 STM32F407, F429

的 NVIC 优先级分组设置为 4,即:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);这样中

断优先级的管理将非常方便。

 用户要在 FreeRTOS 多任务开启前就设置好优先级分组,一旦设置好切记不可再修改。 


事件标志组 API 函数

使用如下 11 个函数可以实现 FreeRTOS 的事件标志组:

 xEventGroupCreate()

 xEventGroupCreateStatic()

 vEventGroupDelete()

 xEventGroupWaitBits()

 xEventGroupSetBits()

 xEventGroupSetBitsFromISR()

 xEventGroupClearBits()

 xEventGroupClearBitsFromISR()

 xEventGroupGetBits()

 xEventGroupGetBitsFromISR() 

这里我们重点的说以下 4 个函数:

 xEventGroupCreate()

 xEventGroupWaitBits()

 xEventGroupSetBits()

 xEventGroupSetBitsFromISR() 


函数 xEventGroupCreate

函数原型:

EventGroupHandle_t xEventGroupCreate( void );

函数描述:

函数 xEventGroupCreate 用于创建事件标志组。

 返回值,如果创建成功, 此函数返回事件标志组的句柄,如果 FreeRTOSConfig.h 文件中定义的 heap

空间不足会返回 NULL

#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 30 * 1024 ) ) 

函数 xEventGroupSetBits

函数原型:

EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, /* 事件标志组句柄 */

const EventBits_t uxBitsToSet ); /* 事件标志位设置 */

函数描述:

函数 xEventGroupSetBits 用于设置指定的事件标志位为 1。

 第 1 个参数是事件标志组句柄。

 第 2 个参数表示 24 个可设置的事件标志位,EventBits_t 是定义的 32 位变量,

低 24 位用于事件标志设置。变量 uxBitsToSet 的低 24 位的某个位设置为 1,那么被设置的

事件标志组的相应位就设置为 1。 变量 uxBitsToSet 设置为 0 的位对事件标志相应位没有影响。比

如设置变量 uxBitsToSet = 0x0003 就表示将事件标志的位 0 和位 1 设置为 1,其余位没有变化。


 返回当前的事件标志组数值。 


使用这个函数要注意以下问题:

1. 使用前一定要保证事件标志组已经通过函数 xEventGroupCreate 创建了。

2. 此函数是用于任务代码中调用的,故不可以在中断服务程序中调用此函数,中断服务程序中使用的是

xEventGroupSetBitsFromISR

3. 用户通过参数 uxBitsToSet 设置的标志位并不一定会保留到此函数的返回值中,下面举两种情况:

a. 如果设置一个位导致等待该位的任务离开阻塞状态,则该位可能会被自动清除(请参阅xEventGroupWaitBits()的xClearBitOnExit参数)。

b. 调用此函数的任务是一个低优先级任务,通过此函数设置了事件标志后,让一个等待此事件标志

的高优先级任务就绪了,会立即切换到高优先级任务去执行,相应的事件标志位会被函数

xEventGroupWaitBits 清除掉,等从高优先级任务返回到低优先级任务后,函数xEventGroupSetBits 的返回值已经被修改。


函数 xEventGroupSetBitsFromISR

函数原型:

BaseType_t xEventGroupSetBitsFromISR(

EventGroupHandle_t xEventGroup, /* 事件标志组句柄 */

const EventBits_t uxBitsToSet, /* 事件标志位设置 */

BaseType_t *pxHigherPriorityTaskWoken ); /* 高优先级任务是否被唤醒的状态保存 */

函数描述:

函数 xEventGroupSetBitsFromISR,用于设置指定的事件标志位为 1。(中断方式)

 第 1 个参数是事件标志组句柄。

 第 2 个参数表示 24 个可设置的事件标志位,EventBits_t 是定义的 32 位变量(详解 18.1.2 小节说

明),低 24 位用于事件标志设置。变量 uxBitsToSet 的低 24 位的某个位设置为 1,那么被设置的

事件标志组的相应位就设置为 1。 变量 uxBitsToSet 设置为 0 的位对事件标志相应位没有影响。比

如设置变量 uxBitsToSet = 0x0003 就表示将事件标志的位 0 和位 1 设置为 1,其余位没有变化。

 第 3 个参数用于保存是否有高优先级任务准备就绪。如果函数执行完毕后,此参数的数值是 pdTRUE,

说明有高优先级任务要执行,否则没有。 

 返回值,如果消息成功发送给 daemon 任务(就是 FreeRTOS 的定时器任务)返回 pdPASS,否则

返回 pdFAIL,另外 daemon 任务中的消息队列满了也会返回 pdFAIL。

使用这个函数要注意以下问题:

1. 使用前一定要保证事件标志已经通过函数 xEventGroupCreate 创建了。同时要在 FreeRTOSConfig.h

文件中使能如下三个宏定义:

#define INCLUDE_xEventGroupSetBitFromISR 1

#define configUSE_TIMERS 1

#define INCLUDE_xTimerPendFunctionCall 1

2. 函数 xEventGroupSetBitsFromISR 是用于中断服务程序中调用的,故不可以在任务代码中调用此函

数,任务代码中使用的是 xEventGroupSetBits。

3. 函数 xEventGroupSetBitsFromISR 对事件标志组的操作是不确定性操作,因为不知道当前有多少个

任务在等待此事件标志。而 FreeRTOS 不允许在中断服务程序和临界段中执行不确定性操作。 为了不

在中断服务程序中执行,就通过此函数给 FreeRTOS 的 daemon 任务(就是 FreeRTOS 的定时器任

务)发送消息,在 daemon 任务中执行事件标志的置位操作。 同时也为了不在临界段中执行此不确定

操作,将临界段改成由调度锁来完成。这样不确定性操作在中断服务程序和临界段中执行的问题就都

得到解决了。

4. 由于函数 xEventGroupSetBitsFromISR 对事件标志的置位操作是在 daemon 任务里面执行的,如果

想让置位操作立即生效,即让等此事件标志的任务能够得到及时执行,需要设置 daemon 任务的优先

级高于使用此事件标志组的所有其它任务。

5. 通过下面的使用举例重点看一下函数 xEventGroupSetBitsFromISR 第三个参数的规范用法,初学者务

必要注意。 

函数 xEventGroupWaitBits

函数原型:

EventBits_t xEventGroupWaitBits(

const EventGroupHandle_t xEventGroup, /* 事件标志组句柄 */

const EventBits_t uxBitsToWaitFor, /* 等待被设置的事件标志位 */

const BaseType_t xClearOnExit, /* 选择是否清零被置位的事件标志位 */

const BaseType_t xWaitForAllBits, /* 选择是否等待所有标志位都被设置 */

TickType_t xTicksToWait ); /* 设置等待时间 */

函数描述:

函数 xEventGroupWaitBits 等待事件标志被设置。

 第 1 个参数是事件标志组句柄。

 第 2 个参数表示等待 24 个事件标志位中的指定标志,EventBits_t 是定义的 32 位变量(详解 18.1.2

小节说明),低 24 位用于事件标志设置。比如设置变量 uxBitsToWaitFor = 0x0003 就表示等待事

件标志的位 0 和位 1 设置为 1。 此参数切不可设置为 0。

 第 3 个参数选择是否清除已经被置位的事件标志,如果这个参数设置为 pdTRUE,且函数

xEventGroupWaitBits 在参数 xTicksToWait 设置的溢出时间内返回,那么相应被设置的事件标志

位会被清零。 如果这个参数设置为 pdFALSE,对已经被设置的事件标志位没有影响。

 第 4 个参数选择是否等待所有的标志位都被设置,如果这个参数设置为 pdTRUE,要等待第 2 个参

数 uxBitsToWaitFor 所指定的标志位全部被置 1,函数才可以返回。当然,超出了在参数

xTicksToWait 设置的溢出时间也是会返回的。如果这个参数设置为 pdFALSE,第 2 个参数

uxBitsToWaitFor 所指定的任何标志位被置 1,函数都会返回,超出溢出时间也会返回。

 第 5 个参数设置等待时间,单位时钟节拍周期。 如果设置为 portMAX_DELAY,表示永久等待。

 返回值,由于设置的时间超时或者指定的事件标志位被置 1,导致函数退出时返回的事件标志组数值。

使用这个函数要注意以下问题:

1. 此函数切不可在中断服务程序中调用。

2. 这里再着重说明下这个函数的返回值,通过返回值用户可以检测是哪个事件标志位被置 1 了。 

 如果由于设置的等待时间超时,函数的返回值可会有部分事件标志位被置 1。

 如果由于指定的事件标志位被置1而返回, 并且设置了这个函数的参数xClearOnExit为pdTRUE,

那么此函数的返回值是清零前的事件标志组数值。

另外,调用此函数的任务在离开阻塞状态到退出函数 xEventGroupWaitBits 之间这段时间,如果一个

高优先级的任务抢占执行了,并且修改了事件标志位,那么此函数的返回值会跟当前的事件标志组数

值不同 。


  实验分析场:



static void AppTaskCreate(void)

{


        xTaskCreate(vTaskWork,       /* 任务函数  */

                 "vTaskWork",         /* 任务名    */

                  512,                   /* 任务栈大小,单位word,也就是4字节 */

                  NULL,                  /* 任务参数  */

                  1,                     /* 任务优先级*/

                  &xHandleTaskWork );  /* 任务句柄  */

    

    

    xTaskCreate( vTaskLed1,            /* 任务函数  */

                 "vTaskLed1",          /* 任务名    */

                 512,                 /* 任务栈大小,单位word,也就是4字节 */

                 NULL,                /* 任务参数  */

                 2,                   /* 任务优先级*/

                 &xHandleTaskLED1); /* 任务句柄  */

    

    xTaskCreate( vTaskBeep,             /* 任务函数  */

                 "vTaskBeep",           /* 任务名    */

                 512,                     /* 任务栈大小,单位word,也就是4字节 */

                 NULL,                   /* 任务参数  */

                 3,                       /* 任务优先级*/

                 &xHandleTaskBeep );  /* 任务句柄  */

    

    

}


 



/*********************************************************************************

  * @ 函数名  : vTaskBeep

  * @ 功能说明: Beep 任务

  * @ 参数    : pvParameters,当任务创建的时候传进来,可以没有  

  * @ 返回值  : 无

  ********************************************************************************/

void vTaskBeep(void *pvParameters)

{

        EventBits_t uxBits;

        const TickType_t xTicksToWait = 5000; /* 最大延迟100ms */

    

    while(1)

    {

        /* 等K1按键按下设置bit0和K2按键按下设置bit1 */

        uxBits = xEventGroupWaitBits(xCreatedEventGroup, /* 事件标志组句柄 */

                                     BIT_ALL,            /* 等待bit0和bit1被设置 */

                                     pdTRUE,             /* 退出前bit0和bit1被清除,这里是bit0和bit1都被设置才表示“退出”*/

                                     pdTRUE,             /* 设置为pdTRUE表示等待bit1和bit0都被设置*/

                                     xTicksToWait);      /* 等待延迟时间 */

        

        if((uxBits & BIT_ALL) == BIT_ALL)

        {

            /* 接收到bit1和bit0都被设置的消息 */

            printf("接收到bit0和bit1都被设置的消息\r\n");

        }

        else

        {

            /* 超时,另外注意仅接收到一个按键按下的消息时,变量uxBits的相应bit也是被设置的 */

            BEEP_TOGGLE; 

        }

    }

}


 


 



/***按键处理任务***/




static void vTaskWork(void *pvParameters)

{


    EventBits_t uxBits;


    while(1)

    {

        

        

        if (key1_flag==1)

        {

            key1_flag=0;

                        /* 设置事件标志组的bit0 */

                    uxBits = xEventGroupSetBits(xCreatedEventGroup, BIT_0);

                    if((uxBits & BIT_0) != 0)

                    {

                        printf("K1键按下,事件标志的bit0被设置\r\n");

                    }

                    else

                    {

                        printf("K1键按下,事件标志的bit0被清除,说明任务vTaskBeep已经接受到bit0和bit1被设置的情况\r\n");

                    }

        }

        if(key2_flag==1)

        {

                    key2_flag=0;

                    uxBits = xEventGroupSetBits(xCreatedEventGroup, BIT_1);

                    if((uxBits & BIT_1) != 0)

                    {

                        printf("K2键按下,事件标志的bit1被设置\r\n");

                    }

                    else

                    {

                        printf("K2键按下,事件标志的bit1被清除,说明任务vTaskBeep已经接受到bit0和bit1被设置的情况\r\n");

                    }

            

        }

    

        

        vTaskDelay(20);

    }

}



创建的任务,按键处理优先级低于事件等待的Beep任务,先按下K1,再按K2,打印如下:



第一个输出毫无疑问,第二行,由于事件等待Beep优先级大于按键处理,所以当K2按下之后,调度器首先回到高优先级的任务Beep,打印出此时K1,K2都被按下以致bit0和bit1被置位的消息,在Beep任务中调用xEventGroupWaitBits函数后,这两个置为1的位bit1和bit0会被清零,此时,调度器再次回到低优先级的按键处理任务时,xEventGroupSetBits的返回值已经更新成清零值,故第三行打印清除的消息。


现在,我们把按键处理的优先级设置成为高于Beep任务的,打印输出如下:

第一个输出也毫无疑问,按下K1,bit0被置位,当我按下K2的时候,此时调度器 不会马上返回低优先级的Beep任务,而会继续执行自身(此实验设置按键处理最高优先级)直到被阻塞,所以会有第二行的打印,但是,注意,第二行按下K2的打印却依旧显示的是被清除了,因为在Beep任务中使用了事件等待,而K2按下的时候,freertos操作系统会知道等待两个按键按下的事件已经触发了,此时,在按键处理任务中,xEventGroupSetBits的返回值,也不是当前获取的置位值了,而是经过xEventGroupSetBits函数自动清零之后的值,所以第二行打印的是清零消息,第三行打印都被置位,为什么不是清零?因为此时的xEventGroupWaitBits返回值是清零前的事件标志组数值。


可能你觉得有点奇怪, xEventGroupSetBits函数本就是置位信息的功能,居然还要受xEventGroupWaitBits函数和调用形式影响,哪怕调用xEventGroupWaitBits函数的任务优先级还是低于我们的按键任务的,但是,正是因为这样,我们真正实时传递了事件信息啊。试想,要是我的两个按键事件都已经触发了,而我在按键处理任务中还不能立即知道,这样的实时性显然是不满足需求的。就连裸机中,我们通过中断改变一个元素的值,一定是中断改变之后,这个值在被任何使用的时候都已经更新,所以,作为实时操作系统,freertos这样的行为也就可以理解了。


 


中断方式不再演示,只是需要在中断服务函数中使用xEventGroupSetBitsFromISR,使用方式如下:



/*

*********************************************************************************************************

*    函 数 名: TIM_CallBack1和TIM_CallBack2

*    功能说明: 定时器中断的回调函数,此函数被bsp_StartHardTimer所调用。                        

*    形    参: 无

*    返 回 值: 无

*********************************************************************************************************

*/

static void TIM_CallBack1(void)

{

    BaseType_t xResult;

    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    

    /* 向任务vTaskBeep发送事件标志 */

    xResult = xEventGroupSetBitsFromISR(xCreatedEventGroup, /* 事件标志组句柄 */

                                        BIT_0 ,             /* 设置bit0 */

                                        &xHigherPriorityTaskWoken );


    /* 消息被成功发出 */

    if( xResult != pdFAIL )

    {

        /* 如果xHigherPriorityTaskWoken = pdTRUE,那么退出中断后切到当前最高优先级任务执行 */

        portYIELD_FROM_ISR(xHigherPriorityTaskWoken);

    }

}


关键字:STM32  事件标志组 引用地址:STM32学习之:事件标志组

上一篇:STM32学习之:NVIC的初步理解
下一篇:STM32学习之:定时器程序设计探讨

推荐阅读最新更新时间:2024-03-16 16:17

STM32学习笔记--------GPIO
1、概述 GPIO,即通用I/O(输入/输出)端口,是STM32可控制的引脚。STM32芯片的GPIO引脚与外部设备连接起来,可实现与外部通讯、控制外部硬件或者采集外部硬件数据的功能。 STM32F103有7组IO。分别为GPIOA~GPIOG,每组IO有16个IO口,共有112个IO口。通常称为 PAx、PBx、PCx、PDx、PEx、PFx、PGx,其中x为0-15,F1系列是基于Cortex-M3内核 2、GPIO工作模式(暂时不做深入研究先用) ─ 输入浮空 ─ 输入上拉 ─ 输入下拉 ─ 模拟输入 ─ 开漏输出 ─ 推挽式输出 ─ 推挽式复用功能 ─ 开漏复用功能 3、GPIO使用 使用步骤 1.硬件时钟
[单片机]
<font color='red'>STM32</font>学习笔记--------GPIO
STM32的小开发板的设计
分析一个STM32的小开发板的设计: 先看2D的预览 底面 多个电容来滤波 一个晶振提供时基 就是长这样 这个是提供一个复位电平 原理图里面都是使用的网络标签,在原理图里面只要一个引脚的名字一样,它就是连在一起的。 选择一个便宜的LDO 最小的原理图 俩脚控制IO,LED 围着三组引脚,名字一样就可以 原理图是简单的,接下来看PCB版图的设计,我感觉PCB最难的地方是这个。 先看看这个布局 设计好的样子是这样的,让我一层一层的往回推,学习它的设计 这里是为了好走线,旋转了一下U,45° 这里就可以旋转了 把文档和顶层丝印层都关了 现在的样子就是这样的 在这里看
[单片机]
<font color='red'>STM32</font>的小开发板的设计
ARM学习《九》——关于STM32的systick定时器的详细说明
我不得不说意法半导体确实有点风骚!甚至有点变态。我对ST文档 STM32F10XXX参考手册的编辑水平真是不敢恭维。手册中好多说明都是含糊不清,甚至将好多对初学者来说很重要的地方都一笔带过,让人着实摸不着头脑。比如前面我说过的关于NVIC嵌套向量中断控制器的介绍,这部分我认为是非常重要的,但当你看完他这部分介绍,你根本不会设置中断服务程序,他有哪些寄存器都不知道,更别说去设置了,NVIC的详细介绍是在Cotex-M3中有详细的介绍,不多说。今天我们说的是systick定时器。 systick定时器和我上面说的情况一样,在手册中根本没有介绍。我费了九牛二虎之力才在一个犄角格拉里找到systick定时器的英文版的说明。在Cote
[单片机]
ARM学习《九》——关于<font color='red'>STM32</font>的systick定时器的详细说明
STM32 USB数据发送完成的识别方法
1 if (GetEPTxStatus(ENDP1) == EP_TX_NAK) 则认为发送完成了 2 可以在相应端点的回调函数中,作相应的标志 void EP1_IN_Callback(void) { sUSB.in = 0; }
[单片机]
STM32单片机的串口波特率计算方法
1. 什么是波特率 不管是什么单片机,在使用串口通信的时候,有一个非常重要的参数:波特率。什么是波特率:波特率就是每秒传送的字节数。双方在传输数据的过程中,波特率一致,这是通讯成功的基本保障。下面以STM32单片机为例,讲解一下串口波特率的计算方法。 2. STM32波特率相关的寄存器 STM32单片机设置波特率的寄存器只有一个:USART_BRR寄存器,如下图所示。 该寄存器的有效位数为16位,前4位用于存放小数部分,后12位用于存放整数部分。将波特率算出来后,数值填入这个波特率就可以了。下面介绍如何计算。 3. 波特率计算方法 STM32的数据手册给出了计算方法,有一个公式,如下图所示: 在这个公式上,共有三个变量
[单片机]
<font color='red'>STM32</font>单片机的串口波特率计算方法
关于stm32中R15寄存器的理解
今天上午看《stm32权威指南》中关于R15寄存器中有些内容不理解,查了查资料,原来是这样。 这里有一个别人的问题。 我把Nor Flash里的一个函数代码数据(函数首地址是:0x6400EC10)拷贝到RAM的 0x2000FC00, 然后把0x2000FC00加载给PC指针(为了让代码在RAM里运行),接着就出现了Hard Fault Exception,而用 IAR 单步执行的时候能正常运行。同时我将一个函数地址值赋给一个unsigned int 变量之后发现自动加了1。对于这些问题先看权威指南里是怎么说的吧。 一,PC指针(程序计数器R15)(权威指南) R15是程序计数器,在汇编代码中称为 PC指针
[单片机]
关于<font color='red'>stm32</font>中R15寄存器的理解
关于STM32-I2C不合理看法
1. 关于 SCL时钟设置的处理。 在软件模拟年代,SCL是50%的PWM, 就是说 SCL低周期:SCL 高周期=1:1, 这是我们一贯的认识与做法。 而实在ATMEL与NXP的 ARM 中的I2C也是如此对待。只不过ATMEL叫TWI. 由于ATMEL公司本身也生产I2C的FLASH和SPI FLASH ; 我们有理由 相信这种1:1是可行可靠的。 我们知道I2C是NXP(菲利普半导体)的专利 ,它应该是权威了, 但我们仔细看NXP的ARM7, 它的I2C 时钟高、低周期 是可变的。 我们可以设1:1,也可以设1:2 等等。虽然NXP 手册上是使用1:1的设计。 简单的说: SCL时钟高低周期比例定了下来(1:1),那
[单片机]
STM32系统架构
在小容量、中容量和 大容量产品中,主系统由以下部分构成: ● 四个驱动单元: ─ Cortex-M3内核DCode总线(D-bus),和系统总线(S-bus) ─ 通用DMA1和通用DMA2 ● 四个被动单元 ─ 内部SRAM ─ 内部闪存存储器 ─ FSMC ─ AHB到APB的桥(AHB2APBx),它连接所有的APB设备 这些都是通过一个多级的AHB总线构架相互连接的,如下图所示: 在互联型产品中,主系统由以下部分构成: ● 五个驱动单元: ─ Cortex-M3内核DCode总线(D-bus),和系统总线(S-bus) ─ 通用DMA1和通用DMA2 ─ 以太网DMA ● 三个被动单元 ─ 内部SRAM ─ 内部闪存
[单片机]
<font color='red'>STM32</font>系统架构
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved