单片机

单片机运行时需要调用某个程序/函数/固定数据时就需要读取ROM,然后在RAM中执行这些程序/函数的功能,所产生的临时数据也都存在RAM内,断电后这些临时数据就丢失了。

ROM:(Read Only Memory)

程序存储器在单片机中用来存储程序数据及常量数据或变量数据。

凡是c文件及h文件中所有代码、全局变量、局部变量、const’限定符定义的常量数据、startup.asm文件中的代码通通都存储在ROM中。

RAM:(Random Access Memory)

随机访问存储器用来存储程序中用到的变量。

凡是整个程序中,所用到的需要被改写的量,都存储在RAM中,“被改变的量”包括全局变量、局部变量、堆栈段。

程序经过编译、汇编、链接后,生成hex文件。

用专用的烧录软件,通过烧录器将hex文件烧录到ROM中。

究竟是怎样将hex文件传输到MCU内部的ROM中的呢?

因此,这个时候的ROM中,包含所有的程序内容。

无论是一行一行的程序代码,函数中用到的局部变量,头文件中所声明的全局变量,const声明的只读常量,都被生成了二进制数据,包含在hex文件中,全部烧录到了ROM里面。

此时的ROM,包含了程序的所有信息,正是由于这些信息,“指导”了CPU的所有动作。

可能有人会有疑问,既然所有的数据在ROM中,那RAM中的数据从哪里来?

什么时候CPU将数据加载到RAM中?

会不会是在烧录的时候,已经将需要放在RAM中数据烧录到了RAM中?

要回答这个问题,首先必须明确一条:ROM是只读存储器,CPU只能从里面读数据,而不能往里面写数据,掉电后数据依然保存在存储器中;

RAM是随机存储器,CPU既可以从里面读出数据,又可以往里面写入数据,掉电后数据不保存,这是条永恒的真理,始终记挂在心。

清楚了上面的问题,那么就很容易想到,RAM中的数据不是在烧录的时候写入的。

因为烧录完毕后,拔掉电源,当再给MCU上电后,CPU能正常执行动作,RAM中照样有数据。

这就说明:RAM中的数据不是在烧录的时候写入的,同时也说明,在CPU运行时,RAM中已经写入了数据。

关键就在这里:这个数据不是人为写入的,CPU写入的,那CPU又是什么时候写入的呢?

听我娓娓道来,上面说到,ROM中包含所有的程序内容,在MCU上电时,CPU开始从第1行代码处执行指令。

这里所做的工作是为整个程序的顺利运行做好准备,或者说是对RAM的初始化(注:ROM是只读不写的),工作任务有几项:

1、为全局变量分配地址空间---à如果全局变量已赋初值,则将初始值从ROM中拷贝到RAM中。

如果没有赋初值,则这个全局变量所对应的地址下的初值为0或者是不确定的。

当然,如果已经指定了变量的地址空间,则直接定位到对应的地址就行,那么这里分配地址及定位地址的任务由“连接器”完成。

2、设置堆栈段的长度及地址---à用C语言开发的单片机程序里面,普遍都没有涉及到堆栈段长度的设置,但这不意味着不用设置。

栈段主要是用来在中断处理时起“保存现场”及“现场还原”的作用,其重要性不言而喻。

而这么重要的内容,也包含在了编译器预设的内容里面,确实省事,可并不一定省心。

3、分配数据段data,常量段const,代码段code的起始地址。

代码段与常量段的地址可以不管,它们都是固定在ROM里面的,无论它们怎么排列,都不会对程序产生影响。

但是数据段的地址就必须得关心。

数据段的数据时要从ROM拷贝到RAM中去的,而在RAM中,既有数据段data,也有堆栈段stack,还有通用的工作寄存器组。

通常,工作寄存器组的地址是固定的,这就要求在绝对定址数据段时,不能使数据段覆盖所有的工作寄存器组的地址。

必须引起严重关注!

这里所说的“第一行代码处”,并不一定是你自己写的程序代码,绝大部分都是编译器代劳的,或者是编译器自带的demo程序文件。

因为,你自己写的程序(C语言程序)里面,并不包含这些内容。

高级一点的单片机,这些内容,都是在startup的文件里面,仔细阅读,有好处的。

通常的做法是:普通的flashMCU是在上电时或复位时,PC指针里面的存放的是“0000”,表示CPU从ROM的0000地址开始执行指令,在该地址处放一条跳转指令,使程序跳转到_main函数中。

然后根据不同的指令,一条一条的执行,当中断发生时(中断数量也很有限,2~5个中断),按照系统分配的中断向量表地址,在中断向量里面,放置一条跳转到中断服务程序的指令,如此如此,整个程序就跑起来了。

决定CPU这样做,是这种ROM结构所造成的。

其实,这里面,C语言编译器作了很多的工作,只是,你不知道而已。

如果你仔细阅读编译器自带的help文件就会知道很多的事情,这是对编译器了解最好的途径。

I/O口寄存器:也是可以被改变的量,它被安排在一个特别的RAM地址,为系统所访问,而不能将其他变量定义在这些位置。

中断向量表:中断向量表是被固定在MCU内部的ROM地址中,不同的地址对应不同的中断。

每次中断产生时,直接调用对应的中断服务子程序,将程序的入口地址放在中断向量表中。

ROM的大小问题:对于flash类型的MCU,ROM空间的大小通常都是整字节的,即为ak*8bits。

这很好理解,一眼就知道,ROM的空间为aK。

但是,对于某些OTP类型的单片机,比如holtek或者sonix公司的单片机,经常看到数据手册上写的是“OTP progarming ROM 2k*15bit。。。。。”。

可能会产生疑惑,这个“15bit”认为是1个字节有余,2个字节又不足,那这个ROM空间究竟是2k,多于2k,还是4k但是少了一点点呢?

这里要明确两个概念:一个是指令的位宽,另一个是指令的长度。

指令的位宽是指一条指令所占的数据位的宽度;有些是8位位宽,有些是15位位宽。

指令长度是指每条指令所占的存储空间,有1个字节,有2个字节的,也有3个字节甚至4个字节的指令。

这个可以打个形象的比方:我们做广播体操时,有很多动作要做,但是每个复杂的动作都可以分解为几个简单的动作。

例如,当做伸展运动时,我们只听到广播里面喊“2、2、3、4、5、6、7、8”。

而这里每一个数字都代表一个指令。

听到“3”这个指令后,我们的头、手、腰、腿、脚分别作出不同的动作:两眼目视前方,左手叉腰,右手往上抬起,五指伸直自然并拢打开,右腿伸直,左腿成弓步······等等一系列的分解动作。

而要做完这些动作的指令只有一个“3”,要执行的动作却又很多,于是将多个分解动作合并成一个指令,而每个分解动作的“位宽”为15bits。

实事上也确实如此,当在反汇编或者汇编时,可以看到,复合指令的确是有简单的指令组合起来的。

到此,回答前面那个问题,这个OTP的ROM空间应该是2K,指令位宽为15位。

一般的,当指令位宽不是8的倍数时,则说明该MCU的大部分指令长度是一个字节(注:该字节宽度为15位,不是8位),极少数为2个或多个字节,虽然其总的空间少,但是其能容下的空间数据并不少。

来源:巧学模电数电单片机
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 93

目前常用的单片机中往往都配备了定时器/计数器。在AT89S52芯片内包含有三个16位的定时器/计数器:T0、T1和T2,其核心是加1计数器。我们主要要求掌握T0和T1的结构和功能。学习中要注意从电路结构上来理解功能的实现。定时器/计数器方式寄存器TMOD和定时器/计数器控制寄存器TCON是用以设定定时器/计数器的工作方式、定时或计数功能,控制启动或停止以及产生溢出中断的重要模块,应该对这两个寄存器中的逐位的定义和功能进行学习和掌握。

“图1:T0和T1的基本构成"
图1:T0和T1的基本构成

一、定时器/计数器的功能

AT89S52单片机定时器/计数器的基本部件是两个8位的计数器(T1计数器分为高8位TH1和低8位TL1,T0计数器的高8位是TH0,低8位是TL0)。如图1所示。

定时器/计数器的核心是一个加1计数器,在作定时器使用时,它对机器周期进行计数,每过一个机器周期计数器加1,直到计数器计满溢出。

当它用作对外部事件计数时,计数器接相应的外部输入引脚T0(P3.4)或T1(P3.5)并在每个机器周期的S5P2时采样,当采样到1—0的负跳变时,计数器加1。

二、定时器/计数器的结构

AT89S52单片机内部的定时/计数器的结构如图2所示。定时器T0由特殊功能寄存器TL0(低8位)和TH0(高8位)构成,定时器T1由特殊功能寄存器TL1(低8位)和TH1(高8位)构成。每个寄存器均可单独访问。

“图2
图2 定时器/计数器的内部结构

1、定时/计数的基本概念

定时和计数是日常生活和生产中最常见和最普遍的问题。

定时器和计数器功能基本上都是使用相同的逻辑实现的,而且这两个功能都包含输入的计数信号,本质上都是对脉冲计数。计数器用来计数并指示在任意间隔内输入信号(事件)的个数,而定时器则对规定间隔内输入的信号个数进行计数,用来指示经历的时间。

在单片机中,定时/计数器作定时功能用时,对机器周期计数(由单片机的晶体振荡器经过12分频后得到),因每次计数的周期是固定的,所以根据它计数的多少就可以很方便的计算出它计数的时间。如图3所示。

“图3
图3 计数与定时

2、溢出的基本概念

从一个生活中的例程看起:一个水盆在水龙头下,水龙头没关紧,水一滴滴地滴入盆中。盆的容量是有限的,水滴持续落下,盆中的水持续变满,最终有一滴水使得盆中的水满了,这就是“溢出”。

如果一个空的盆要1万滴水滴进去才会满,开始滴水之前可以先放入一部分水,叫做计数初值。如果现在要计数9000,那么可以先放入1000滴水,也就是计数初值为1000,再计数9000就可以溢出产生中断。

单片机中通常采用计数初值的办法,如果每个脉冲是1微秒,则计满256个脉冲需时256微秒,如果现在要定时100微妙,只要在计数器里面先放进156,然后计数100就可以就可以溢出产生中断了。如图4所示。

“图4
图4 定时器/计数器的溢出

3、定时/计数的主要方法

实现定时或计数,主要有三种方法。

(1)软件延时

软件延时利用微处理器执行一个延时程序段实现。因为微处理器执行每条指令都需要一定时间,通过指令的循环实现软件延时。软件定时具有不使用硬件的特点,但却占用了大量CPU时间。另外,软件定时精度不高,在不同系统时钟频率下,执行一条指令的时间不同,同一个软件延时程序的定时时间也会不同。

(2)硬件定时

硬件定时采用数字电路中的分频器将系统时钟进行适当分频产生需要的定时信号,也可以采用单稳电路或简易定时电路(如常用的555定时器)由外接RC(电阻、电容)电路控制定时时间。这样的定时电路较简单,利用不同分频倍数或改变电阻阻值、电容容值使定时时间在一定范围内改变。

(3)可编程的硬件定时

可编程定时器/计数器最大特点是可以通过软件编程来实现定时时间的改变,通过中断或查询方法来完成定时功能或计数功能。这种电路不仅定时值和定时范围可用程序改变,而且具有多种工作方式,可以输出多种控制信号,具备较强的功能。

来源:网络
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:
cathy@eetrend.com)。

围观 218

沁恒微电子推出了带有Type-C PD和USB双功能的单片机CH543,采用E8051内核,集成USB主机控制器和收发器,支持全速或低速的USB Host或USB Device功能、集成Type-C PD PHY带有DMA功能及灵活的中断配置,可方便地用于各种Source、Sink及DRP场景的PD通讯应用。

“沁恒微电子推出带有Type-C

“内部结构框图"
内部结构框图

CH543主要特点

1· 16KB Flash-ROM + 256B EEPROM + 32B OTP ROM + 512B RAM

2· 内置LDO,支持3.3~12V电源电压

3· 支持USB2.0全速/低速,支持Host主机/Device设备模式

4· 内置USB PD收发器PHY,支持DMA收发数据

5· 带有I²C从控制器,支持1MHz时钟

6· 4路PWM输出,支持驱动全桥

7· 9位可编程灌电流,支持PD PPS

8· 12通道12位ADC,有内置运放

9· Touch-Key、UART、SPI等其他外设

CH543内部还带有I²C从机控制器,可以方便的配合其他控制器,从CH543中读取数据及状态信息。这在笔记本、平板电脑、电动工具等带有锂电池充电需求的应用中可以提供很大的便利。

同时,CH543还集成有一个9位灌电流源,可以直接用于调节电源系统如DC-DC、TL431的FB反馈引脚。配合芯片内部集成的可高达12V输入电压的LDO、开漏输出引脚等功能,可以方便的实现可高度定制的PD电源、拓展坞、多媒体类应用。

Type-C转DP显示+USB3.0的典型应用

下图为一款Type-C转DP显示+USB3.0的典型应用框图。其中CH543在应用中负责Type-C正反插检测及切换控制、Type-C PD通讯与笔记本/平板电脑等设备握手进入显示模式、检测显示器接入/移除并通知主机。CH9445为一款差分高速信号双向模拟开关芯片,高宽带,低导通电阻,可通过I²C接口配置,实现2对高达5Gbps(USB3.1 Gen2),4对高达8Gbps(DisplayPort 1.4),和1对480Mbps(DisplayPort AUX,或USB2.0高速)信号的矩阵切换。

“CH543:支持12V的PD电源管理MCU"

CH543在Type-C PD电源中的典型应用

下图为CH543在Type-C PD电源中的典型应用框图。其中CH543通过FB端连接TL431或者DC-DC的参考电压端,用于3.3~12V的Type-C PD Source角色应用。

“CH543:支持12V的PD电源管理MCU"

来源:沁恒微电子
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 923

01、方案描述:

本方案采用瑞萨RA系列R7FA2E1A52DFJ实现无叶风扇的控制方案,通过PWM输出控制风扇运转,利用触摸按键控制无叶风扇功能,以及通过高精度AD采集电池充电电压,防止过冲,显示面板显示电量,转速等参数,该方案外设资源丰富,运行稳定可靠。

02、产品介绍

无叶电风扇的基座中带有40瓦电力马达,它每秒钟将33升的空气吸入风扇基座内部。再经由气旋加速器加速后,空气流通速度被增大16倍左右,接着被无叶电风扇的扇头环形内唇环绕,其环绕力带动扇头附近的空气随之进入扇头,并以每秒405升的速度向外吹出。

一、瑞萨RA2E1系列R7FA2E1A52DFJ芯片的适用性

方案框图里选用了R7FA2E1A52DFJ开发,具备以下丰富外设资源

1、内置大容量32K Flash与丰富外设资源,对于客户方案应用开发提供了更多的选择。

2、内置12位高精度,高速ADC,适合客户过压精准采样。

3、内置PWM控制设置方便控制电机运转。

4、内置大容量的4K Data Flash,能保存用户的设定数据和用户大量的使用数据。

5、支持超低功耗,对于锂电应用场景提高了超长续航的能力。

6、该系列MCU集成了触摸感应单元,可以实现在触摸面板,触摸按键上的应用。

二、瑞萨ISL8117 DCDC芯片参数特性

1、4.5-60V输入,输出0.6-54V。

2、12 Ld 4x3 DFN和16 Ld TSSOP封装。

三、RA MCU开发环境

RA系列使用瑞萨IDE e2 studio开发,里面集成FSP底层代码生成器与参考应用代码,给工程师开发提供了高效,便捷的工具。

四、无叶风扇设计框图

“基于瑞萨RA系列R7FA2E1A52DFJ

五、各部分电路概述

1、系统电源经过ISL8117产生3.3V对MCU芯片供电。

2、通过触摸按键可以方便调整无叶风扇的功能和参数。

3、MCU产生PWM,驱动MOS,控制无叶风扇的旋转。

4、MCU通过ADC模块采集到的电池电压信号,控制过冲电路的工作状态。

5、显示面板通过I2C接口与MCU通讯,显示实时温度与电量。

6、蜂鸣器电路通过声音,提醒用户异常特殊情况的提示。

7、LED显示当前的电量档位,并显示报警信息。

“控制板图片和产品图片"
控制板图片和产品图片

来源:瑞萨MCU小百科(作者:Eric Yuan)
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 59

随着微电子技术和计算机技术的发展,原来以强电和电器为主、功能简单的电气设备发展成为强、弱电结合,具有数字化特点、功能完善的新型微电子设备。

在很多场合,已经出现了越来越多的单片机产品代替传统的电气控制产品。单片机其控制功能通过软件指令来实现,其硬件配置也可变、易变。因此,一旦生产过程有所变动,就不必重新设计线路连线安装,有利于产品的更新换代和订单式生产。

传统电气设备采用的各种控制信号,必须转换到与单片机输入/输出口相匹配的数字信号。用户设备须输入到单片机的各种控制信号,如限位开关、 操作按钮、选择开关、行程开关以及其他一些传感器输出的开关量等,通过输入电路转换成单片机能够接收和处理的信号。输出电路则应将单片机送出的弱电控制信 号转换、放大到现场需要的强输出信号,以驱动功率管、电磁阀和继电器、接触器、电动机等被控制设备的执行元件,能方便实际控制系统使用。

针对电气控制产品的特点,本文讨论了几种单片机I/O的常用驱动和隔离电路的设计方法,对合理地设计电气控制系统,提高电路的接口能力,增强系统稳定性和抗干扰能力有实际指导意义。

输入电路设计

一般输入信号最终会以开关形式输入到单片机中,以工程经验来看,开关输入的控制指令有效状态采用低电平比采用高电平效果要好得多,如图1所示。当按下开关S1时,发出的指令信号为低电平,而平时不按下开关S1时,输出到单片机上的电平则为高电平。该方式具有较强的耐噪声能力。

“图1
图1 开关信号输入

若考虑到由于TTL电平电压较低,在长线传输中容易受到外界干扰,可以将输入信号提高到+24 V,在单片机入口处将高电压信号转换成TTL信号。这种高电压传送方式不仅提高了耐噪声能力,而且使开关的触点接触良好,运行可靠,如图2所示。其 中,D1为保护二极管,反向电压≥50 V。

“图2
图2 提高输入信号电平

“图3
图3 输入端保护电路

为了防止外界尖峰干扰和静电影响损坏输入引脚,可以在输入端增加防脉冲的二极管,形成电阻双向保护电路,如图3所示。二极管D1、D2、 D3的正向导通压降UF≈0.7 V,反向击穿电压UBR≈30 V,无论输入端出现何种极性的破坏电压,保护电路都能把该电压的幅度限制在输入端所能承受的范围之内。即:VI~VCC出现正脉冲时,D1正向导 通;VI~VCC出现负脉冲时,D2反向击穿;VI与地之间出现正脉冲时,D3反向击穿;VI与地之间出现负脉冲时,D3正向导通,二极管起钳位保护作用。缓冲电阻RS约为1.5~2.5 kΩ,与输入电容C构成积分电路,对外界感应电压延迟一段时间。若干扰电压的存在时间小于τ,则输入端承受的有效电压将远低于其幅度;若时间较长,则D1 导通,电流在RS上形成一定的压降,从而减小输入电压值。

此外,一种常用的输入方式是采用光耦隔离电路。如图4所示,R为输入限流电阻,使光耦中的发光二极管电流限制在10~20 mA。输入端靠光信号耦合,在电气上做到了完全隔离。

同时,发光二极管的正向阻抗值较低,而外界干扰源的内阻一般较高,根据分压原理,干扰源能馈送到输入 端的干扰噪声很小,不会产生地线干扰或其他串扰,增强了电路的抗干扰能力。

“图4
图4 输入端光耦隔离

在满足功能的前提下,提高单片机输入端可靠性最简单的方案是:在输入端与地之间并联一只电容来吸收干扰脉冲,或串联一只金属薄膜电阻来限制流入端口的峰值电流。

输出电路设计

单片机输出端口受驱动能力的限制,一般情况下均需专用的接口芯片。其输出虽因控制对象的不同而千差万别,但一般情况下均满足对输出电压、电流、开关频率、波形上升下降速率和隔离抗干扰的要求。在此讨论几种典型的单片机输出端到功率端的电路实现方法。

1、直接耦合

在采用直接耦合的输出电路中,要避免出现图5所示的电路。

“图5
图5 错误的输出电路

T1截止、T2导通期间,为了对T2提供足够的基极电流,R2的阻值必须很小。因为T2处于射极跟随器方式工作,因此为了减少T2损耗,必须将集射间电压降控制在较小范围内。

这样集基间电压也很小,电阻R2阻值很小才能提供足够的基极电流。R2阻值过大,会大幅度增加T2压降,引起T2发热严重。而在T2截止期间,T1必须导通,高压+15 V全部降在电阻R2上,产生很大的电流,显然是不合理的。

另外,T1的导通将使单片机高电平输出被拉低至接近地电位,引起输出端不稳定。T2基极被T1拉 到地电位,若其后接的是感性负载,由于绕组反电势的作用,T2的发射极可能存在高电平,容易引起T2管基射结反向击穿。

图6为一直接耦合输出电路,由T1和T2组成耦合电路来推动T3。T1导通时,在R3、R4的串联电路中产生电流,在R3上的分压大于T2 晶体管的基射结压降,促使T2导通,T2提供了功率管T3的基极电流,使T3变为导通状态。当T1输入为低电平时,T1截止,R3上压降为零,T2截止, 最终T3截止。R5的作用在于:一方面作为T2集电极的一个负载,另一方面T2截止时,T3基极所储存的电荷可以通过电阻R3迅速释放,加快T3的截止速度,有利于减小损耗。

“图6
图6 直接耦合输出电路

2.TTL或CMOS器件耦合

若单片机通过TTL或CMOS芯片输出,一般均采用集电极开路的器件,如图7(a)所示。集电极开路器件通过集电极负载电阻R1接至+15 V电源,提升了驱动电压。但要注意的是,这种电路的开关速度低,若用其直接驱动功率管,则当后续电路具有电感性负载时,由于功率管的相位关系,会影响波形 上升时间,造成功率管动态损耗增大。

为了改善开关速度,可采用2种改进形式输出电路,如图7(b)和图7(c)所示。图7(b)是能快速开通的改进电路,当TTL输出高电平 时,输出点通过晶体管T1获得电压和电流,充电能力提高,从而加快开通速度,同时也降低了集电极开路TTL器件上的功耗。图7(c)为推挽式的改进电路, 采用这种电路不但可提高开通时的速度,而且也可提高关断时的速度。输出晶体管T1是作为射极跟随器工作的,不会出现饱和,因而不影响输出开关频率。

“图7
图7 TTL或CMOS器件输出电路

3、脉冲变压器耦合

脉冲变压器是典型的电磁隔离元件,单片机输出的开关信号转换成一种频率很高的载波信号,经脉冲变压器耦合到输出级。由于脉冲变压器原、副边线圈间没有电路连接,所以输出是电平浮动的信号,可以直接与功率管等强电元件耦合,如图8所示。

“图8
图8 脉冲变压器输出电路

这种电路必须有一个脉冲源,脉冲源的频率是载波频率,应至少比单片机输出频率高10倍以上。脉冲源的输出脉冲送入控制门G,单片机输出信号 由另一端输入G门。当单片机输出高电平时,G门打开,输出脉冲进入变压器,变压器的副线圈输出与原边相同频率的脉冲,通过二极管D1、D2检波后经滤波还 原成开关信号,送入功率管。当单片机输出低电平时,G门关闭,脉冲源不能通过G门进入变压器,变压器无输出。

这里,变压器既传递信号,又传送能量,提高了脉冲源的频率,有利于减轻变压器的体重。由于变压器可通过调整电感量、原副边匝数等来适应不同 推动功率的要求,所以应用起来比较灵活。更重要的是,变压器原副边线圈之间没有电的联系,副线圈输出信号可以跟随功率元件的电压而浮动,不受其电源大小的 影响。

当单片机输出较高频率的脉冲信号时,可以不采用脉冲源和G门,对变压器原副边电路作适当调整即可。

4、光电耦合

光电耦合可以传输线性信号,也可以传输开关信号,在输出级应用时主要用来传递开关信号。

如图9所示,单片机输出控制信号经缓冲器7407放大后送入光耦。R2为光耦输出晶体管的负载电阻,它的选取应保证:在光耦导通时,其输出晶体管可靠饱和;而在光耦截止时,T1可靠饱和。但由于光耦响应速度慢使开关延迟时间加长,限制了其使用频率。

“图9
图9 光耦输出电路

结语

单片机接口技术在很多资料中均有详细的介绍,但在对大量电气控制产品的改造和设计中,经常会碰到用接口芯片所无法解决的问题(如驱动电流大、开关速度慢、抗干扰差等),因此必须寻求另一种电路解决方案。

上述几种输入/输出电路通过广泛的应用表明,其对合理、可靠地实现单片机电气控制系统具有较高的工程实用价值。

来源:网络
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:
cathy@eetrend.com)。

围观 123

↓↓ 抽奖方式详见文末 ↓↓

与郭天祥老师一起学习GD32F303系列主流型MCU开发实践

15年前,《十天学会单片机》系列视频课程如同一把火炬,点燃了整个单片机教育行业。它颠覆了传统的单片机教学风格,并配套开发板,至今累计下载量数千万次,已成为当今单片机入门普及不可或缺的一套优秀的视频教程。作为视频制作者的他,也成为了无数单片机爱好者的启蒙老师。

2009年,他又编著了《新概念51单片机C语言教程》,书籍上市后很快成为业内知名的教材,至今累计印刷30余次,销量达50多万册,连续多年销量排行同类书籍榜首,目前已经成为诸多高校的学生教材。

他就是大名鼎鼎的郭天祥,被电子爱好者们亲切地称为“郭老师”。无论是自学成才的单片机爱好者,或是在校学习电子专业的大学生,都通过这套视频和教材深受裨益。

“单片机大神郭天祥老师"
单片机大神郭天祥老师

❖ 2007年出版《十天学会单片机》系列视频教程

❖ 2009年编著《新概念51单片机C语言教程》

❖ 2012年创办北京海克智动科技开发有限公司

❖ 2020年开通"郭天祥老师"视频号讲解电子知识

❖ 2021年携手兆易创新GD32开展Arm MCU讲座

行业深耕廿余载

郭天祥老师深刻体会到,创作和分享优质知识内容是情怀更创造价值。知识口耳相授、长久流传,既可以帮助他人,也能够提升自我。怀抱着为电子行业持续培养人才的信念,以”强我强国,科技兴国“为己任,郭天祥老师自2020年12月在各视频平台开通"郭天祥老师"账号,深入浅出地讲解电子知识点,短短1年多时间,已汇聚了100多万名电子工程师和学生订阅收藏。

“”

MCU风潮来袭

近年来受到疫情和国际贸易争端的影响,电子元器件缺货、涨价的新闻层出不穷。国产化替代和供应保障已成为大势所趋,眼下正是产品开发导入的黄金窗口期。郭天祥老师在视频中谈到的联合中国领先的MCU厂商,重点推广中国自主的MCU嵌入式技术和应用。现已正式揭开谜底!

郭天祥老师与中国本土MCU“头把交椅”兆易创新GigaDevice合作,重磅推出《GD32F303系列MCU培训课程》,基于GD32F303系列讲授Arm MCU的开发设计和应用实践。由郭天祥老师和《十天学会单片机》系列视频时期的创业伙伴叶大鹏老师共同授课。为广大行业用户、嵌入式工程师、电子发烧友打造时下最受欢迎的优质内容,分享给大家在课本上学不到,但恰恰又是工作中经常用到的“葵花宝典”。

此番与兆易创新的强强联合,郭天祥老师正是看中了GD32 MCU庞大的用户群体和杰出的市场口碑。无论是丰富完善的MCU产品家族,还是已经得到多年验证的行业认可,都能为郭老师的课程提供施展和发挥的平台。兆易创新也相信通过郭老师标志性接地气的讲课风格,能让更多的行业从业者,真正实现“踏实学芯片、上手做项目”,培养出更多满足当下社会和企业的刚需人才。

“单片机大神郭天祥老师携手兆易创新GD32重出江湖,掀起MCU学习风暴!"

北京兆易创新科技股份有限公司(GigaDevice)成立于2005年,总部设于中国北京,并于2016年8月在上海证券交易所主板上市,目前拥有超过1300名员工,是一家致力于开发先进的存储器技术、MCU和传感器解决方案的领先半导体公司。

作为兆易创新的核心产品线之一,GD32 MCU是中国高性能通用微控制器领域的领跑者,中国最大的Arm MCU家族,也是中国首个Arm Cortex-M3/M4/M23/M33 MCU产品系列,并且在全球范围内首个推出RISC-V内核通用32位MCU产品系列。产品通过长期市场检验,连续六年在中国32位MCU市场位列本土厂商第一。以累计超过10亿颗的出货数量,超过2万家客户数量,35个系列近400余款型号选择所提供的广阔应用覆盖率稳居中国本土首位。现已成为系统设计与项目开发的创新首选。

GD32F303系列主流型MCU

F3系列是兆易创新于2017年推出的基于Arm Cortex-M4内核的经典主流型MCU产品,以优异的市场表现屡获殊荣。今年更推出多个全新型号,覆盖更全更广,更添供货保障!

“单片机大神郭天祥老师携手兆易创新GD32重出江湖,掀起MCU学习风暴!"

当下郭老师以GD32F303系列MCU为主题的Arm培训课程为系统开发工程师,电子爱好者奉上一场深入浅出的技术盛宴,助力单片机行业蓬勃发展和国产化替代的殷切需求。

GD32F303系列MCU视频课程内容

∎ 兆易创新公司及产品线介绍

∎ GD32F303芯片整体介绍及开发环境讲解

∎ 时钟、GPIO、中断子系统解读与实验

∎ 串口、ADC子系统解读与实验

∎ 定时器子系统解读与实验

∎ I2C、SPI串行总线解读与实验

∎ SDIO子系统解读与实验

∎ CAN子系统解读与实验

∎ USBD子系统解读与实验

∎ 行业应用案例介绍

3/10(周四)至4/28(周四)晚上8点起

每周两期(周二、周四)

“单片机大神郭天祥老师携手兆易创新GD32重出江湖,掀起MCU学习风暴!"

在西瓜、抖音、头条、知乎、B站、好看、视频号、YouTube、PN学堂自有平台等主流视频平台同时播出,在各平台搜索“郭天祥老师”关注即可查阅学习。

此外,GD32MCU微信视频号和技术网站也将同步收录系列培训课程,共同为广大用户提供优质的MCU原创视频知识库。

“单片机大神郭天祥老师携手兆易创新GD32重出江湖,掀起MCU学习风暴!"

收看GD32F303系列MCU培训视频并积极参与互动的小伙伴,还有机会获赠与本次课程配套的GD32F303E-EVAL全功能评估板以及其它精美礼品,参见上图,即刻添加微信“pnxuetang”加入群组参与幸运抽奖!

来源:电子创新网张国斌
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 274

公共场所的喷泉一般只是将音乐和喷泉高低简单配合, 或者是采用了高成本复杂的控制系统,搭建复杂的外围电路实现功能;并且多数只能在现场观赏,不能进入家庭。

本文主要介绍基于海速芯TM52F1376单片机控制的小型室内移动式音乐喷泉。它使用了较少的外围器件和较为简单的电路设计,成本低、体积小、水型变换多样,实用性强,适合室内观赏。

系统设计

该系统采集音乐信号,根据音乐信号的强弱来控制水泵电机的转速以及LED彩灯的亮灭。系统的总体结构由音乐输入部分、音响放大部分、单片机控制部分和输出控制部分组成。TM52F1376单片机作为系统的主芯片,一方面采集音乐信号,另一方面依据采集到的音乐信号的强弱输出延时不等的矩形波来控制可控硅的导通时间,进而控制水泵电机的转速,从而达到控制喷水高度的目的。彩灯的亮灭也由单片机依据音乐采样值的大小来控制。

系统硬件设计

硬件系统由单片机电路、音频电路、水泵控制电路、彩灯控制电路、电源电路等组成。

单片机电路

单片机要采集音乐信号,并据此调节I/O口的输出来控制水泵和彩灯。主芯片TM52F1376是8051架构的通用微控制器,片内集成多种功能,包括8K/16K字节的Flash程序存储器,128字节的EEPROM数据存储器,512字节SRAM,低电压复位(LVR),低电压检测(LVD),双时钟省电工作模式,8051标准UART和定时器Timer0/Timer1/Timer2,实时计时器Timer3,LCD/LED驱动器,3组16位脉冲宽度调制器,24通道的12位模数转换器(ADC),I2C串口和看门狗定时器(WDT)等等。

这样不仅可以简化单片机的外围电路,而且处理速度和灵活度都大大增强,并且具有片内调试电路,设计调试周期短。

“封装类型:LQFP32/SOP28/SSOP28/QFN28/SSOP24/SOP20/TSSOP20/QFN20/SOP16"
封装类型:LQFP32/SOP28/SSOP28/QFN28/SSOP24/SOP20/TSSOP20/QFN20/SOP16

总体来讲,设计的喷泉控制系统可基于TM52F1376单片机,采用音频放大、可控硅控制等简洁的外围电路,经过焊接、组装、调试后,很好地实现控制功能,具有很强的实用性,尤其是具有体积小、易移动、适合家庭和室内使用的特点。本方案也可以在功能上加以扩展,如加上对乐曲的频域分析,结合频域特点控制水泵;还可以制作雾化器来渲染效果等。

来源:国芯思辰
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 48

在平常的项目开发过程中,会遇到各种各样的问题,下面分享一篇文章,是常见问题的解决思路和解决办法。

1、问题复现

稳定复现问题才能正确的对问题进行定位、解决以及验证。一般来说,越容易复现的问题越容易解决。

1.1 模拟复现条件

有的问题存在于特定的条件下,只需要模拟出现问题的条件即可复现。对于依赖外部输入的条件,如果条件比较复杂难以模拟可以考虑程序里预设直接进入对应状态。

1.2 提高相关任务执行频率

例如某个任务长时间运行才出现异常则可以提高该任务的执行频率。

1.3 增大测试样本量

程序长时间运行后出现异常,问题难以复现,可以搭建测试环境多套设备同时进行测试。

2、问题定位

缩小排查范围,确认引入问题的任务、函数、语句。

2.1 打印LOG

根据问题的现象,在抱有疑问的代码处增加LOG输出,以此来追踪程序执行流程以及关键变量的值,观察是否与预期相符。

2.2 在线调试

在线调试可以起到和打印LOG类似的作用,另外此方法特别适合排查程序崩溃类的BUG,当程序陷入异常中断(HardFault,看门狗中断等)的时候可以直接STOP查看call stack以及内核寄存器的值,快速定位问题点。

2.3 版本回退

使用版本管理工具时可以通过不断回退版本并测试验证来定位首次引入该问题的版本,之后可以围绕该版本增改的代码进行排查。

2.4 二分注释

二分注释即以类似二分查找法的方式注释掉部分代码,以此判断问题是否由注释掉的这部分代码引起。
具体方法为将与问题不相干的部分代码注释掉一半,看问题是否解决,未解决则注释另一半,如果解决则继续将注释范围缩小一半,以此类推逐渐缩小问题的范围。

2.5 保存内核寄存器快照

Cortex M内核陷入异常中断时会将几个内核寄存器的值压入栈中,如下图:

“30个单片机常见问题解决办法!"

我们可以在陷入异常中断时将栈上的内核寄存器值写入RAM的一段复位后保留默认值的区域内,执行复位操作后再从RAM将该信息读出并分析,通过PC、LR确认当时执行的函数,通过R0-R3分析当时处理的变量是否异常,通过SP分析是否可能出现栈溢出等。

3、问题分析处理

结合问题现象以及定位的问题代码位置分析造成问题的原因。

3.1 程序继续运行

3.1.1 数值异常

3.1.1.1 软件问题

1、数组越界

写数组时下标超出数组长度,导致对应地址内容被修改。

如下:

“30个单片机常见问题解决办法!"

此类问题通常需要结合map文件进行分析,通过map文件观察被篡改变量地址附近的数组,查看对该数组的写入操作是否存在如上图所示不安全的代码,将其修改为安全的代码。

2、栈溢出

0x20001ff8 g_val
0x20002000 栈底
………… 栈空间
0x20002200 栈顶

如上图,此类问题也需要结合map文件进行分析。假设栈从高地址往低地址增长,如果发生栈溢出,则g_val的值会被栈上的值覆盖。

出现栈溢出时要分析栈的最大使用情况,函数调用层数过多,中断服务函数内进行函数调用,函数内部申明了较大的临时变量等都有可能导致栈溢出。

解决此类问题有以下方法:

  • 在设计阶段应该合理分配内存资源,为栈设置合适的大小;
  • 将函数内较大的临时变量加”static”关键字转化为静态变量,或者使用malloc()动态分配,将其放到堆上;
  • 改变函数调用方式,降低调用层数。

3、判断语句条件写错

“30个单片机常见问题解决办法!"

判断语句的条件容易把相等运算符“==”写成赋值运算符“=”导致被判断的变量值被更改,该类错误编译期不会报错且总是返回真。

建议将要判断的变量写到运算符的右边,这样错写为赋值运算符时会在编译期报错。还可以使用一些静态代码检查工具来发现此类问题。

4、同步问题

例如操作队列时,出队操作执行的过程中发生中断(任务切换),并且在中断(切换后的任务)中执行入队操作则可能破坏队列结构,对于这类情况应该操作时关中断(使用互斥锁同步)。

5、优化问题

“30个单片机常见问题解决办法!"

如上图程序,本意是等待irq中断之后不再执行foo()函数,但被编译器优化之后,实际运行过程中flg可能被装入寄存器并且每次都判断寄存器内的值而不重新从ram里读取flg的值,导致即使irq中断发生foo()也一直运行,此处需要在flg的申明前加“volatile”关键字,强制每次都从ram里获取flg的值。

3.1.1.2 硬件问题

1、芯片BUG

芯片本身存在BUG,在某些特定情况下给单片机返回一个错误的值,需要程序对读回的值进行判断,过滤异常值。

2、通信时序错误

“30个单片机常见问题解决办法!"

例如电源管理芯片Isl78600,假设现在两片级联,当同时读取两片的电压采样数据时,高端芯片会以固定周期通过菊花链将数据传送到低端芯片,而低端芯片上只有一个缓存区.

如果单片机不在规定时间内将低端芯片上的数据读走那么新的数据到来时将会覆盖当前数据,导致数据丢失。此类问题需要仔细分析芯片的数据手册,严格满足芯片通信的时序要求。

3.1.2 动作异常

3.1.2.1 软件问题

1、设计问题

设计中存在错误或者疏漏,需要重新评审设计文档。

2、实现与设计不符

代码的实现与设计文档不相符需要增加单元测试覆盖所有条件分支,进行代码交叉review。

3、状态变量异常

例如记录状态机当前状态的变量被篡改,分析该类问题的方法同前文数值异常部分。

3.1.2.2 硬件问题

1、硬件失效

目标IC失效,接收控制指令后不动作,需要排查硬件。

2、通信异常

与目标IC通信错误,无法正确执行控制命令,需要使用示波器或逻辑分析仪去观察通信时序,分析是否发出的信号不对或者受到外部干扰。

3.2 程序崩溃

3.2.1 停止运行

3.2.1.1 软件问题

1、HardFault

以下情况会造成HardFault:

  • 在外设时钟门未使能的情况下操作该外设的寄存器;
  • 跳转函数地址越界,通常发生在函数指针被篡改,排查方法同数值异常;
  • 解引用指针时出现对齐问题:

以小端序为例,如果我们声明了一个强制对齐的结构体如下:

“30个单片机常见问题解决办法!"

“30个单片机常见问题解决办法!"

此时a.val1的地址为0x00000001,如果以uint16_t类型去解引用此地址则会因为对齐问题进入HardFault,如果一定要用指针方式操作该变量则应当使用memcpy()。

2、中断服务函数中未清除中断标志

中断服务函数退出前不正确清除中断标志,当程序执行从中断服务函数内退出后又会立刻进入中断服务函数,表现出程序的“假死”现象。

3、NMI中断

调试时曾遇到SPI的MISO引脚复用NMI功能,当通过SPI连接的外设损坏时MISO被拉高,导致单片机复位后在把NMI引脚配置成SPI功能之前就直接进入NMI中断,程序挂死在NMI中断中。这种情况可以在NMI的中断服务函数内禁用NMI功能来使其退出NMI中断。

3.2.1.2 硬件问题

① 晶振未起振
② 供电电压不足
③ 复位引脚拉低

3.2.2 复位

3.2.2.1 软件问题

看门狗复位

除了喂狗超时导致的复位以外,还要注意看门狗配置的特殊要求,以Freescale KEA单片机为例,该单片机看门狗在配置时需要执行解锁序列(向其寄存器连续写入两个不同的值),该解锁序列必须在16个总线时钟内完成,超时则会引起看门狗复位。此类问题只能熟读单片机数据手册,注意类似的细节问题。

3.2.2.2 硬件问题

① 供电电压不稳
② 电源带载能力不足

4、回归测试

问题解决后需要进行回归测试,一方面确认问题是否不再复现,另一方面要确认修改不会引入其他问题。

5、经验总结

总结本次问题产生的原因及解决问题的方法,思考类似问题今后如何防范,对相同平台产品是否值得借鉴,做到举一反三,从失败中吸取经验。

原文:https://www.cnblogs.com/jozochen/p/8541714.html

来源:小麦大叔
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 55

智能电表和HVAC控制器等连接到网络的设备不仅需要具备实时性能,以同时实现复杂的系统执行和网络通信。还需要定期更新固件(FW),以确保持续稳定的应用。

也就是说,负责设备主控的单片机也需要上述性能和功能。那么您是否希望拥有一款在单个芯片中实现这些特性的单片机,以及一款能够对其进行轻松评测的套件呢?

今天,我为大家介绍的就是能够满足上述要求的32位单片机RX66N,以及能够轻松快速地进行评测和PoC试制的评测套件Target board for RX66N。

RX66N卓越的实时性能完全得益于它搭载的CPU和闪存。由RX系列独有RXv3内核组成的CPU在120MHz的主频下可提供707CoreMark的卓越性能,而4MB闪存能够确保CPU以零等待周期运行,因此即使运行的是闪存中存储的代码,也能够保持较高的处理速度。

“32位单片机RX66N帮您解决联网设备面临的难题"

另外,4MB闪存可以实现方便固件更新的双存储区配置,再配合后台操作功能,在系统运行过程中也可以将更新固件下载到闪存中。

“32位单片机RX66N帮您解决联网设备面临的难题"

此外,RX66N还配备有Target board for RX66N套件,可对上述特性进行轻松评测。该套件搭载有仿真电路,只需使用USB线与PC连接即可轻松评测RX66N卓越的实时性能。并且该套件通过将Wi-Fi模块连接到板载Pmod连接器,可以实现基于实际场景中RTOS操作的云连接,以及构建基于网络的固件更新系统。

“32位单片机RX66N帮您解决联网设备面临的难题"

利用针对RX系列的云解决方案以及固件更新用中间件*和样例程序,还可简单快捷地进行评测和PoC试制。

*点击链接查看:RX产品家族系列技术干货分享(八)-介绍可以轻松实现RX系列FOTA(Firmware Update Over-The-Air)固件更新的中间件

如果您对RX66N Target Board感兴趣,并希望体验卓越的实时性能以及可轻松实现固件更新的闪存,那么RX66N绝对是您的不二选择。在下次的相关文章中,我将实际使用RX66N Target Board来为大家展示它的固件更新功能。敬请期待!

来源:瑞萨电子
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。

围观 24

嵌入式编程的需求千变万化,要做到系统稳定,又要代码可复用,就要做到高内聚低耦合。

前言

我们通常认为,在中断中,不能执行耗时的操作,否则会影响系统的稳定性,尤其对于嵌入式编程。对于带操作系统的程序而言,可以通过操作系统的调度,将中断处理分成两个部分,耗时的操作可以放到线程中去执行,但是对于没有操作系统的情况,又应该如何处理呢

比较常见的,我们可能会定义一些全局变量,作为flag,然后在mainloop中不停的判断这些flag,再在中断中修改这些flag,最后在mainloop中执行具体的逻辑,但是这样,无疑会增加耦合,增加程序维护成本。

cpost

cpost正是应用在这种情况下的一个简单但又十分方便的工具,它可以特别方便的进行上下文的切换,减少模块耦合。

cpost链接:

https://github.com/NevermindZZT/cpost

cpost借鉴的Android的handler机制,通过在mainloop中跑一个任务,然后在其他地方,可以是中断,也可以是模块逻辑中,直接抛出需要执行的函数,使其脱离调用处的上下文,运行在mainloop中。cpost还支持延迟处理,可以指定函数在抛出后多久执行

使用

cpost的使用十分简单,这里以使用在嵌入式无操作系统中为例,主要用作中断延迟处理的情况

1、配置系统tick

配置cpost.h中的宏CPOST_GET_TICK(),配置成获取系统tick,以stm32 hal为例

#define     CPOST_GET_TICK()            HAL_GetTick()

2、配置处理进程

在mainloop调用cpostProcess函数

int main(void)
{
    ...
    while (1)
    {
        cpostProcess();
    }
    return 0;
}

3、抛出任务

在中断等需要进行上下文切换的地方调用cpsot接口,使其在mainloop中运行

cpost(intHandler);

原理解析

cpost的原理其实很简单,其代码量也十分少,总共加起来就只有几十行代码,cpost维护了一个而全局的数组

CpostHandler cposhHandlers[CPOST_MAX_HANDLER_SIZE] = {0};

其中,数组的每一个元素表示包含了需要执行的函数和参数,当调用cpost接口时,被post的函数和参数会被保存在这个数组中,然后mainloop中运行的cpostProcess函数会遍历这个数组,当满足条件时,执行对应的函数,从而达到上下文切换的目的

void cpostProcess(void)
{
    for (size_t i = 0; i < CPOST_MAX_HANDLER_SIZE; i++)
    {
        if (cposhHandlers[i].handler)
        {
            if (cposhHandlers[i].time == 0 || CPOST_GET_TICK() >= cposhHandlers[i].time)
            {
                cposhHandlers[i].handler(cposhHandlers[i].param);
                cposhHandlers[i].handler = NULL;
            }
        }
    }
}

其实,cpost的方式,和一开始提到的使用全局的flag进行上下文切换的方法很像,只不过,cpost通过一个数组的维护和直接post函数的方式,省去了维护flag的成本,也不需要将需要执行的函数耦合到mianloop中,从而变得简单易用。

完美解耦 - cevent应用

对于模块化编程来说,如何实现各模块间的解耦一直是一个比较令人头疼的问题,特别是对于嵌入式编程,由于控制逻辑复杂,并且对程序体积有控制,经常容易写出各独立模块之间相互调用的问题。由此,cpost中的cevent组件,通过模仿Android系统中的广播机制,提供了一种非常简单的模块间解耦实现。

原理

cevent借鉴的是Android系统的广播机制,一方面,各模块在工作的时候,都会有多个具体的事件点,在高耦合的编程中,可能会在这些地方调用其他模块的功能,比如说,在通信模块接收到指令的时候,需要闪烁一下指示灯。

使用cevent,我们可以在这些地方抛出一个事件,当前模块不需要关心在这各地方需要执行哪些其他模块的逻辑,由其他模块,或者用户定义一个事件监听,当具体的事件发生时,执行相应的动作。

使用

cevent使用注册的方式监听事件,会依赖于编译环境,目前支持keil,iar,和gcc,对于gcc,需要修改链接文件(.ld),在只读数据区添加:

_cevent_start = .;
KEEP (*(cEvent))
_cevent_end = .;

1、初始化cevent

系统初始化时,调用ceventInit

ceventInit();

2、注册cevent事件监听

在c文件中,调用CEVENT_EXPORT导出事件监听

CEVENT_EXPORT(0, handler, (void *)param);

3、发送cevent事件

在事件发生的地方,调用ceventPost抛出事件

ceventPost(0);

使用cevent解耦模块初始化

嵌入式编程中,我们习惯会在程序启动的时候,调用各个模块的初始化函数,其实这也是一种耦合,会造成main函数中出现很长的初始化代码,借助cevent,我们可以对初始化进行优化解耦。

1、定义初始化事件

定义初始化事件的值,对于初始化,有些模块可能会依赖于其他模块的初始化,会有一个先后顺序要求,所以这里我们可以把初始化分成两个阶段,定义两个事件,当然,如果有更复杂的要求,可以再多分几个阶段,只需要多定义几个事件就行

#define     EVENT_INIT_STAGE1       0
#define     EVENT_INIT_STAGE2       1

2、初始化cevent,抛出事件

在main函数中初始化cevent,并抛出初始化事件

int main(void)
{
    ...
    ceventInit();

    ceventPost(EVENT_INIT_STAGE1);
    ceventPost(EVENT_INIT_STAGE2);
    ...
    return 0;
}

3、注册事件监听

对所有需要初始化的函数注册事件监听,这里我以对letter-shell注册事件监听为例,分为两个部分,初始化串口和初始化shell。

在serial模块中,将串口初始化注册到初始化第一阶段,cevent支持将不大于7个的参数直接传递到注册的监听函数中,下面的注册方式,相当于在EVENT_INIT_STAGE1事件发生的地方,也就是main函数中对应的位置,调用serialInit(&debugSerial)

CEVENT_EXPORT(EVENT_INIT_STAGE1, serialInit, (void *)(&debugSerial));

然后再shell模块中,将shell初始化函数注册到初始化第二阶段。

CEVENT_EXPORT(EVENT_INIT_STAGE1, shellInit);

使用cevent解耦mainloop

再无操作系统的嵌入式编程中,我们如果同时希望运行多个模块的逻辑,通常是在mainloop中循环调用,这种将函数写入mainloop的做法,也会增加耦合

int main(void)
{
    ...

    while (1)
    {
        // 写在mainloop中的模块逻辑
        shellTask(&shell);
        LedProcess();
        ...
    }
    return 0;
}

通过使用cevent,也可以很方便的消除这种耦合

1、定义mainloop事件

定义mainloop事件的值

#define     EVENT_MAIN_LOOP         3

2、在mainloop中抛出事件

去掉mainloop中对其他模块的调用,改为排除mainloop事件

int main(void)
{
    ...

    while (1)
    {
        ceventPost(EVENT_MAIN_LOOP);
    }
    return 0;
}

3、在各模块中注册事件监听

分别在各个模块中,注册对mainloop事件的监听

CEVENT_EXPORT(EVENT_MAIN_LOOP, shellTask, (void *)(&shell));
CEVENT_EXPORT(EVENT_MAIN_LOOP, LedProcess);

结语

cevent是一个非常小的模块,本身代码及其简单,但是,通过模仿广播机制,让cevent可以发挥很强大的功能,通过,还可以结合cpost,实现延迟事件等功能。

来源:
https://blog.csdn.net/qq_34245464/article/details/111804661

围观 61

页面

订阅 RSS - 单片机