当前位置:首页 > 单片机
  • 一文看懂STM32单片机和51单片机区别

    一文看懂STM32单片机和51单片机区别

    01 前言 单片微型计算机简称单片机,简单来说就是集CPU(运算、控制)、RAM(数据存储-内存)、ROM(程序存储)、输入输出设备(串口、并口等)和中断系统处于同一芯片的器件,在我们自己的个人电脑中,CPU、RAM、ROM、I/O这些都是单独的芯片,然后这些芯片被安装在一个主板上,这样就构成了我们的PC主板,进而组装成电脑,而单片机只是将这所有的集中在了一个芯片上而已。 02 51单片机简介 应用最广泛的8位单片机当然也是初学者们最容易上手学习的单片机,最早由Intel推出,由于其典型的结构和完善的总线专用寄存器的集中管理,众多的逻辑位操作功能及面向控制的丰富的指令系统,堪称为一代“经典”,为以后的其它单片机的发展奠定了基础。 51单片机之所以成为经典,成为易上手的单片机主要有以下特点: AD、EEPROM等功能需要靠扩展,增加了硬件和软件负担。 虽然I/O脚使用简单,但高电平时无输出能力,这也是51系列单片机的最大软肋。 运行速度过慢,特别是双数据指针,如能改进能给编程带来很大的便利。 51保护能力很差,很容易烧坏芯片。 目前在教学场合和对性能要求不高的场合大量被采用。 使用最多的器件:8051、80C51 03 STM32单片机简介 由ST厂商推出的STM32系列单片机,行业的朋友都知道,这是一款性价比超高的系列单片机,应该没有之一,功能及其强大。其基于专为要求高性能、低成本、低功耗的嵌入式应用专门设计的ARM Cortex-M内核,同时具有一流的外设:1μs的双12位ADC,4兆位/秒的UART,18兆位/秒的SPI等等,在功耗和集成度方面也有不俗的表现,当然和MSP430的功耗比起来是稍微逊色的一些,但这并不影响工程师们对它的热捧程度,由于其简单的结构和易用的工具再配合其强大的功能在行业中赫赫有名…其强大的功能主要表现在: 内核:ARM32位Cortex-M3CPU,最高工作频率72MHz,1.25DMIPS/MHz,单周期乘法和硬件除法。 存储器:片上集成32-512KB的Flash存储器。6-64KB的SRAM存储器。 时钟、复位和电源管理:2.0-3.6V的电源供电和I/O接口的驱动电压。POR、PDR和可编程的电压探测器(PVD)。4-16MHz的晶振。内嵌出厂前调校的8MHz RC振荡电路。内部40 kHz的RC振荡电路。用于CPU时钟的PLL。带校准用于RTC的32kHz的晶振。 调试模式:串行调试(SWD)和JTAG接口。最多高达112个的快速I/O端口、最多多达11个定时器、最多多达13个通信接口。 使用最多的器件:STM32F103系列、STM32 L1系列、STM32W系列。 04 51单片机和STM32单片机的区别 51单片机是对所有兼容Intel8031指令系统的单片机的统称,这一系列的单片机的始祖是Intel的8031单片机,后来随着flash ROM技术的发展,8031单片机取得了长足的进展成为了应用最广泛的8bit单片机之一,他的代表型号就是ATMEL公司的AT89系列。 STM32单片机则是ST(意法半导体)公司使用arm公司的cortex-M3为核心生产的32bit系列的单片机,他的内部资源(寄存器和外设功能)较8051、AVR和PIC都要多的多,基本上接近于计算机的CPU了,适用于手机、路由器等等。 本文来源于网络,如有侵权,请联系删除 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-01-21 关键词: STM32 单片机 51单片机

  • 单片机系统EMC测试和故障排除

    01 前言 对于从事单片机应用系统(软硬件)设计的工程技术人员来说,掌握一定的EMC测试技术是十分必要的。 02 关于EMC EMC:Electromagnetic Compatibility,即电磁兼容性。指设备或系统在其电磁环境中符合要求运行并不对其环境中的任何设备产生无法忍受的电磁骚扰的能力。 它包括电磁干扰(EMI)和电磁敏感性(EMS)两部分。由于电器产品在使用时对其它电器有电磁干扰,或受到其它电器的电磁干扰,它不仅关系到产品工作的可靠性和安全性,还可能影响其它电器的正常工作,甚至导致安全危险。 03 EMC测试两大内容 1.对其向外界发送的电磁骚扰强度进行测试,以便确认是否符合有关标准规定的限制值要求; 2.对其在规定电磁骚扰强度的电磁环境条件下进行敏感度测试,以便确认是否符合有关标准规定的抗扰度要求。 04 单片机系统EMC测试 4.1 测试环境 为了保证测试结果的准确和可靠性,电磁兼容性测量对测试环境有较高的要求,测量场地有室外开阔场地、屏蔽室或电波暗室等。 4.2 测试设备 电磁兼容测量设备分为两类:一类是电磁干扰测量设备,设备接上适当的传感器,就可以进行电磁干扰的测量;另一类是在电磁敏感度测量,设备模拟不同干扰源,通过适当的耦合/去耦网络、传感器或天线,施加于各类被测设备,用作敏感度或干扰度测量。 4.3 测量方法 电磁兼容性测试依据标准的不同,有许多种测量方法,但归纳起来可分为4类;传导发射测试、辐射发射测试、传导敏感度(抗扰度)测试和辐射敏感度(抗扰度)测试。 4.4 测试诊断步骤 下图给出了一个设备或系统的电磁干扰发射与故障分析步骤。按照这个步骤进行,可以提高测试诊断的效率。 4.5 测试准备 ①试验场地条件:EMC测试实验室为电波半暗室和屏蔽室。前者用于辐射发射和辐射敏感测试,后者用于传导发射和传导敏感度测试。 ②环境电平要求:传导和辐射的电磁环境电平最好远低于标准规定的极限值,一般使环境电平至少低于极限值6dB。 ③试验桌。 ④测量设备和被测设备的隔离。 ⑤敏感性判别准则:一般由被测方提供,并实话监视和判别,以测量和观察的方式确定性能降低的程度。 ⑥被测设备的放置:为保证实验的重复性,对被测设备的放置方式通常有具体的规定。 4.6 测试种类 传导发射测试、辐射发送测试、传导抗扰度测试、辐射抗扰度测试。 4.7 常用测量仪 电磁干扰(EMI)和电磁敏感度(EMS)测试,需要用到许多电子仪器,如频谱分析仪、电磁场干扰测量仪、信号源、功能放大器、示波器等。由于EMC测试频率很宽(20Hz~40GHz)、幅度很大(μV级至kW级)、模式很多(FM、AM等)、姿态很多(平放、斜放等),因此正确地使用电子仪器非常重要。 测量电磁干扰的合适仪器是频谱分析仪。频谱分析仪是一种将电压幅度随频率变化的规律显示出来的仪器,它显示的波形称为频谱。频谱分析仪克服了示波器在测量电磁干扰中的缺点,能够精确测量各个频率上的干扰强度,用频谱分析仪可以直接显示出信号的各个频谱分量。 05 电磁兼容故障排除技术 5.1 传导型问题的解决 ①通过串联一个高阻抗来减少EMI电流。 ②通过并联一个低阻抗将EMI电流短路到地或引到其它回路导体。 ③通过电流隔离装置切断EMI电流。 ④通过其自身作用来抑制EMI电流。 5.2 电磁兼容的容性解决方案 一种常见的现象是不把滤波电容的一侧看成直接与一个分离的阻抗相连,而看成与传输线相连。典型的情况是,当一条输入输出线的长度达到或超过1/4波长时,该传输线变“长”。 实际可以用下式近似表示这种变化:l≥55/f 式中:l单元为m,f单位为MHz。这个公式考虑了平均传播速度,它是自由空间理论的0.75倍。 a. 电介质材料及容差 电磁干扰滤波使用的大部分电容是无极性电容。 b. 差模(线到线)滤波电容性电容。 c. 共模(线到地/机壳)滤波电容 共模(CM)去耦通常使用小电容(10~100nF)。小电容可以将不期望的高频电流在其进入敏感电路之前或在其离噪声电路较远时就将其短路到机壳上去。为了得到良好的高频衰减电路,减小或消除寄生电感是关键之所在。因此有必要使用超短导线,尤其希望使用无引线元器件。 5.3 感性、串联损耗电磁兼容解决方案 就电容而言,Zs和Z1如果不是纯电阻的话,在计算频率时,要使用它们的实际值。电容器串联在电源或信号电路时,必须满足: ①流过的工作电流不应该引起电感过热或过大的有过之而无不及降; ②流过的电流不能引起电感磁饱和,尤其是对高导磁材料是毫无疑问的。 解决方案有以下几种: 磁芯材料; 铁氧体和加载铁氧体的电缆; 电感、差模和共模; 接地扼流圈; 组合式电感电容元件。 5.4 辐射型问题的解决 在很多情况下,辐射电磁干扰问题可能在传导阶段产生并被排除,还有些解决方案是可以抑制干扰装置在辐射传输通道上,就像场屏蔽那样工作。根据屏蔽理论,这种屏蔽的效果主要取决于电磁干扰源的频率、与屏蔽装置之间的距离以及电磁干扰场的特性——电场、磁场或者平面波。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-01-21 关键词: 故障 EMC 单片机

  • 搞懂八个技术点,就学会了单片机

    01 复位电路设计 关于复位电路的详细解释,可以查看下面的链接: 单片机基础入门:什么是上电复位,复位电路怎么设计 02 LED串联电阻的计算问题 在设计LED驱动电路时,一定要注意LED的正向导通电压,关于LED驱动电路的设计,可以查看下面的链接: 这时可以借助扩展芯片来实现,比如三八译码器74HC138/移位寄存器74HC595等来拓展。 滤波电容分为高频滤波电容和低频滤波电容。 高频滤波电容一般用104容(0.1uF),目的是短路高频分量,保护器件免受高频干扰。普通的IC(集成)器件的电源与地之间都要加,去除高频干扰(空气静电)。 低频滤波电容一般用电解电容(100uF),目的是去除低频纹波,存储一部分能量,稳定电源。大多接在电源接口处,大功率元器件旁边,如:USB接口、步进电机、1602背光显示。耐压值至少高于系统最高电压的2倍。 05 三极管的作用 单片机输出高电平时,三极管导通;单片机输出低电平时,三极管截至。三极管作为开关驱动继电器可以查看下面的链接: 单片机能直接驱动继电器吗?三极管驱动继电器的电路怎么设计 三极管具有三个工作区: 截至区 、 线性区 、 饱和区 。用作放大作用时,三极管工作在线性区。这一块是模电的老大难。三极管是如何实现放大作用的,查看下面的链接: 三极管必知基础知识:线性放大 当基极为高电平时,三极管导通,右侧的导线接地为低电平,当基极为低电平时,三极管截止,输出高电平。 06 数码管的相关问题 上拉电阻选取原则 从节约功耗及芯片灌电流能力考虑应当足够大;电阻大,电流小。 从确保足够的驱动电流考虑应当足够小;电阻小,电流大。 对于高速电路,过大的上拉电阻可能会导致边沿变平缓。 综合考虑:上拉电阻常用值在1K到10K之间选取,下拉同理。 上下拉电阻 上拉就是将不确定的信号通过一个电阻嵌位在高电平,下拉同理。 电平转换,提高输出电平参数值。 OC门必须加上拉电阻才能使用。 加大普通IO引脚驱动能力。 悬空引脚上下拉抗干扰。 08 按键抖动及消除 软件除抖是检测出键闭合后执行一个延时程序,产生5ms~10ms的延时,让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有键按下。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-01-21 关键词: 复位电路 单片机

  • 学会单片机的UART,就学会了通信,UART详解

    UART协议,由Tx和Rx两根数据线组成,因为没有参考时钟信号,所以通信的双方必须约定串口波特率、奇偶校验位等配置参数,从而按照相同的速率进行通信。 异步通信以一个字符为传输单位,通信中两个字符间的时间间隔多少是不固定的,然而在同一个字符中的两个相邻位间的时间间隔是固定的。当波特率为9600bps时,传输一个bit的时间间隔大约为104.16us;波特率为115200bps时,传输一个bit的时间间隔大约为8us。 数据传送速率用波特率来表示,即每秒钟传送的二进制位数。例如数据传送速率为120字符/秒,而每一个字符为10位(1个起始位,7个数据位,1个校验位,1个结束位),则其传送的波特率为10×120=1200字符/秒=1200波特。 数据通信时序图: 其中各位的意义如下: 起始位:先发出一个逻辑”0”信号,表示传输字符的开始; 数据位:可以是5~8位逻辑”0”或”1”;如ASCII码(7位),扩展BCD码(8位);小端传输,即LSB先发,MSB后发; 校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验); 停止位:它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平(用于双方同步,停止位时间间隔越长,容错能力越强); 空闲位:处于逻辑“1”状态,表示当前线路上没有数据传送; 注:异步通信是按字符传输的,接收设备在收到起始信号之后只要在一个字符的传输时间内能和发送设备保持同步就能正确接收。下一个字符起始位的到来又使同步重新校准(依靠检测起始位来实现发送与接收方的时钟自同步的)。 ↑图-1 起始位和停止位 ↑图-2 数据位 ↑传输“A” 上图是uart协议传输一个”A”字符通过示波器的uart解码而得到的波形示意图。根据此图来介绍一下uart的一些基本参数。 波特率:此参数容易和比特率混淆,其实他们是由区别的。但是我认为uart中的波特率就可以认为是比特率,即每秒传输的位数(bit)。一般选波特率都会有9600,19200,115200等选项。其实意思就是每秒传输这么多个比特位数(bit)。 起始位:先发出一个逻辑”0”的信号,表示传输数据的开始。 数据位:可以选择的值有5,6,7,8这四个值,可以传输这么多个值为0或者1的bit位。这个参数最好为8,因为如果此值为其他的值时当你传输的是ASCII值时一般解析肯定会出问题。理由很简单,一个ASCII字符值为8位,如果一帧的数据位为7,那么还有一位就是不确定的值,这样就会出错。 校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性。就比如传输“A”(01000001)为例。 1、当为奇数校验:”A”字符的8个bit位中有两个1,那么奇偶校验位为1才能满足1的个数为奇数(奇校验)。图-1的波形就是这种情况。 2、当为偶数校验:”A”字符的8个bit位中有两个1,那么奇偶校验位为0才能满足1的个数为偶数(偶校验)。 此位还可以去除,即不需要奇偶校验位。 停止位:它是一帧数据的结束标志。可以是1bit、1.5bit、2bit的空闲电平。可能大家会觉得很奇怪,怎么会有1.5位~没错,确实有的。所以我在生产此uart信号时用两个波形点来表示一个bit。这个可以不必深究。。。 空闲位:没有数据传输时线路上的电平状态。为逻辑1。 传输方向:即数据是从高位(MSB)开始传输还是从低位(LSB)开始传输。比如传输“A”如果是MSB那么就是01000001(如图-2),如果是LSB那么就是10000010(如下图的图-4) uart传输数据的顺序就是:刚开始传输一个起始位,接着传输数据位,接着传输校验位(可不需要此位),最后传输停止位。这样一帧的数据就传输完了。接下来接着像这样一直传送。在这里还要说一个参数。 帧间隔:即传送数据的帧与帧之间的间隔大小,可以以位为计量也可以用时间(知道波特率那么位数和时间可以换算)。比如传送”A”完后,这为一帧数据,再传”B”,那么A与B之间的间隔即为帧间隔。 ↑图-3 ↑图-4 上两图和下两图传送的数据和波特率都是一样的,但是有几个参数是故意设置反了从而形成对比。有助于更深入的理解UART。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-01-21 关键词: 通信 UART 单片机

  • 单片机红外电路设计原理

    电视、空调都离不开红外遥控器。空调遥控器其实就是一个红外信号发射装置,而空调机身具有红外接收探头,可以接收遥控器发出的红外信号并解析,从而实现遥控的功能,电视遥控器也是同样的原理。现在有很多手机具有红外功能,通过匹配通讯协议,就能实现手机遥控电视和空调的作用。下面通过 硬件 和 软件 两个方面来和大家分享,红外遥控实现的原理。 本部分内容包括, 红外发射部分原理 、 红外接收部分原理 以及 软件编码部分原理 。 2 红外接收部分电路原理 前文说过,红外发射和红外接收是一对,成对使用。发射管是白色的,接收管是黑色的。可以使用三极管搭建接收电路也可以使用比较器来搭建电路,下面用三极管电路展示红外接收的电路。如下图所示。 在没有接收到红外信号时,接收管不导通,三极管Q1不导通,三极管Q3不导通,单片机接收到持续的高电平;当接收管接收到红外信号时,单片机接收到低电平。当遥控器的按键被按下时,按键对应的编码脉冲就会被单片机所接收到,单片机解析该脉冲,就能知道遥控器上是哪个按键被按下,从而实现用户的操作。 但是,黑色的红外接收管抗干扰能力比较低,在设计电路的时候一般不选用,而是选用专用的红外接收头,最常用的型号为HS0038。而且,其红外接收电路简单,抗干扰能力强。 3 红外软件编码解析

    时间:2021-01-21 关键词: 原理 红外电路 单片机

  • 单片机常用的几种通信接口,I2C、SPI、UART等

    文章直接来源:嵌入式大杂烩 在嵌入式系统中,板上通信接口是指用于将各种集成电路与其他外围设备交互连接的通信通路或总线。以下内容为常用板上通信接口:包括I2C、SPI、UART、1-Wire: I2C总线 I2C总线是一种 同步、双向、半双工的两线式串行接口总线。这里,半双工的含义是指在任意给定的时刻,只有一个方向上是可以通信的。 I2C总线最早由Philips半导体公司于20世纪80年代研发面市。I2C最初的设计目标是为微处理器/微控制器系统与电视机外围芯片之间的连接提供简单的方法。 I2C总线由两条总线组成:串行时钟线SCL和串行数据线SDA。 SCL线——负责产生同步时钟脉冲。 SDA线——负责在设备间传输串行数据。 I2C总线是共享的总线系统,因此可以将多个I2C设备连接到该系统上。连接到I2C总线上的设备既可以用作主设备,也可以用作从设备。 主设备负责控制通信,通过对数据传输进行初始化/终止化,来发送数据并产生所需的同步时钟脉冲。 从设备则是等待来自主设备的命令,并响应命令接收。主设备和从设备都可以作为发送设备或接收设备。无论主设备是作为发送设备还是接收设备,同步时钟信号都只能由主设备产生。 在相同的总线上,I2C支持多个主设备的同时存在。图1-1显示了I2C总线上主设备和从设备的连接关系。 当总线空闲时,SDA 和SCL 都处于高电平状态,当主机要和某个从机通讯时,会先发送一个开始条件,然后发送从机地址和读写控制位,接下来传输数据(主机发送或者接收数据),数据传输结束时主机会发送停止条件。传输的每个字节为8 位,高位在前,低位在后。 开始条件:SCL 为高电平时,主机将SDA 拉低,表示数据传输即将开始。 从机地址:主机发送的第一个字节为从机地址,高7 位为地址,最低位为R/W 读写控制位,1 表示读操作,0 表示写操作。 一般从机地址有7 位地址模式和10 位地址模式两种,如果是10 位地址模式,第一个字节的头7 位是11110XX 的组合,其中最后两位(XX)是10 位地址的两个最高位,第二个字节为10 位从机地址的剩下8 位,如下图所示: 应答信号:每传输完成一个字节的数据,接收方就需要回复一个ACK(acknowledge)。写数据时由从机发送ACK,读数据时由主机发送ACK。当主机读到最后一个字节数据时,可发送NACK(Notacknowledge)然后跟停止条件。 数据:从机地址发送完后可能会发送一些指令,依从机而定,然后开始传输数据,由主机或者从机发送,每个数据为8 位,数据的字节数没有限制。 重复开始条件:在一次通信过程中,主机可能需要和不同的从机传输数据或者需要切换读写操作时,主机可以再发送一个开始条件。 停止条件:在SDA 为低电平时,主机将SCL 拉高并保持高电平,然后在将SDA 拉高,表示传输结束。 SPI总线 SPI总线是 同步、双向、全双工的4线式串行接口总线,最早由Motorola公司提出。SPI是由“单个主设备+多个从设备”构成的系统。需要说明的是:在系统中,只要任意时刻只有一个主设备是处于激活状态的,就可以存在多个SPI主设备。常运用于EEPROM、FLASH、实时时钟、AD转换器、数字信号处理器和数字信号解码器之间实现通信。 为了实现通信,SPI共有4条信号线,分别是: (1)主设备出、从设备入(Master Out Slave In,MOSI):由主设备向从设备传输数据的信号线,也称为从设备输入(Slave Input/Slave Data In,SI/SDI)。 (2)主设备入、从设备出(Master In Slave Out,MISO):由从设备向主设备传输数据的信号线,也称为从设备输出(Slave Output/Slave Data Out,SO/SDO)。 (3)串行时钟(Serial Clock,SCLK):传输时钟信号的信号线。 (4)从设备选择(Slave Select,SS):用于选择从设备的信号线,低电平有效。 SPI使用方法: 上图所示芯片有2 个SPI 控制器,SPI 控制器对应SPI 主设备,每个SPI 控制器可以连接多个SPI从设备。挂载在同一个SPI 控制器上的从设备共享3 个信号引脚:SCK、MISO、MOSI,但每个从设备的CS 引脚是独立的. 主设备通过控制CS 引脚对从设备进行片选,一般为低电平有效。任何时刻,一个SPI 主设备上只有一个CS 引脚处于有效状态,与该有效CS 引脚连接的从设备此时可以与主设备通信。 所以,SPI通信方式可以使用“一主多从”的结构进行通信。每个连接到总线上的器件都有唯一的地址,主设备启动数据传输并产生时钟信号,从设备被主设备寻址,同一时刻只允许有一个主设备。 从设备的时钟由主设备通过SCLK 提供,MOSI、MISO 则基于此脉冲完成数据传输。SPI 的工作时序模式由CPOL(Clock Polarity,时钟极性)和CPHA(Clock Phase,时钟相位)之间的相位关系决定,CPOL 表示时钟信号的初始电平的状态,CPOL 为0 表示时钟信号初始状态为低电平,为1 表示时钟信号的初始电平是高电平。CPHA 表示在哪个时钟沿采样数据,CPHA 为0 表示在首个时钟变化沿采样数据,而CPHA 为1 则表示在第二个时钟变化沿采样数据。 根据CPOL 和CPHA 的不同组合共有4 种工作时序模式:CPOL=0,CPHA=0、CPOL=0,CPHA=1、CPOL=1,CPHA=0、CPOL=1,CPHA=1 UART UART—— 通用异步收发传输器,UART 作为异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输。在应用程序开发过程中使用频率较高的数据总线。 基于UART的数据传输是异步形式的串行数据传输。基于UART的串行数据传输不需要使用时钟信号来同步传输的发送端和接收端,而是依赖于发送设备和接收设备之间预定义的配置。 对于发送设备和接收设备来说,两者的串行通信配置(波特率、单位字的位数、奇偶校验、起始位数与结束位、流量控制)应该设置为完全相同。通过在数据流中插入特定的比特序列,可以指示通信的开始与结束。当发送一个字节数据的时候,需要在比特流的开头加上起始位,并在比特流的末尾加上结束位。数据字节的最低位紧接在起始位之后。 UART 串口的特点是将数据一位一位地顺序传送,只要2 根传输线就可以实现双向通信,一根线发送数据的同时用另一根线接收数据。 UART 串口通信有几个重要的参数,分别是波特率、起始位、数据位、停止位和奇偶检验位,对于两个使用UART 串口通信的端口,这些参数必须匹配,否则通 起始位:表示数据传输的开始,电平逻辑为“0” 。 数据位:可能值有5、6、7、8、9,表示传输这几个bit 位数据。一般取值为8,因为一个ASCII 字符值为8 位。 奇偶校验位:用于接收方对接收到的数据进行校验,校验“1” 的位数为偶数(偶校验) 或奇数(奇校验),以此来校验数据传送的正确性,使用时不需要此位也可以。 停止位:表示一帧数据的结束。电平逻辑为“1”。 波特率:串口通信时的速率,它用单位时间内传输的二进制代码的有效位(bit) 数来表示,其单位为每秒比特数bit/s(bps)。常见的波特率值有4800、9600、14400、38400、115200 等,数值越大数据传输的越快,波特率为115200 表示每秒钟传输115200 位数据。 1-Wire接口 1-Wire接口是由Maxim Dallas半导体公司(首页为http://www.maxim-ic.com)开发的 异步半双工通信协议,也称为Dallas 1-Wire®协议。其中,按照主-从通信模型,只使用单条信号线DQ实现通信。 1-Wire总线的一个重要特征在于,该总线允许在信号线上传输能量。1-Wire接口支持在总线上连接单个主设备以及一个或多个从设备。 并行接口 板上并行接口(parallel interface)通常用于系统与外围设备之间的通信,其中,外围设备通过存储器映射到系统的主控端。只要嵌入式系统的主控处理器/控制器含有并行总线,支持并行总线的设备就可以直接连接到该总线系统上。外围设备与主控端之间具有控制信号接口,可以控制并行总线上的数据通信。这里,通信的控制信号包括读/写信号和设备选择信号。一般说来,外围设备具有设备选择线;只有当主控处理器选通该线的时候,该设备才是有效的。 数据传输的方向可以是从主控端到外围设备,也可以是从外围设备到主控端;这是通过读和写控制信号线进行控制的。只有主控处理器能够控制读控制信号和写控制信号。一般说来,外围设备通过存储器映射到主控处理器,从而可以访问分配的地址范围。此时,设备需要使用地址译码电路来产生芯片选择信号。 当处理器选择的地址位于设备指定范围内的时候,译码电路对芯片选择线进行触发,从而激活设备。然后,处理器可以使能相应的控制线(分别是RD\与WD\),从而由设备读出数据,或者是向设备写入数据。 为了实现并行通信,系统需要严格遵循时序规范。前面已经提到过,并行通信是由主控处理器启动的。如果某外围设备想要对通信进行初始化,那么可以向处理器发出中断,告知相关信息。为了实现上述功能,设备的中断线需要连接到处理器的中断线上,并且主控处理器需要触发相应的中断。需要说明的是,主控处理器的数据总线宽度决定了并行接口的宽度,可以是4位、8位、16位、32位、64位等。设备支持的总线宽度应该与主控处理器完全相同。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-01-21 关键词: 嵌入式 通信接口 单片机

  • STM32单片机外部晶振无效?那是因为配置不对?

    1.问题的提出 新项目用到STM32单片机,用到了500k波特率的CAN通讯,因此没有使用内部晶振,而是用到了12M的外部晶振。该项目的程序员在调试的时候发现,STM32的时钟频率不对,于是我给帮忙看了一下,找到了原因。 2.Datasheet上的答案 通过翻阅单片机的datasheet我们知道,STM32默认的外部晶振频率为8M,可输出72M的频率。于是找到了库函数的一段注释,如下: The default value of HSE crystal is set to 8 MHz (or 25 MHz, depedning on the product used), refer to "HSE_VALUE" define in "stm32f10x.h" file.When HSE is used as system clock source, directly or through PLL and you are using different crystal you have to adapt the HSE value to your own configuration. 根据描述,将stm32f10x.h中大约在0121行将8000000修改为 12000000。 //微信公众号:玩转嵌入式,ID:micropoint8 #if !defined  HSE_VALUE #ifdef STM32F10X_CL #define HSE_VALUE    ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */ #else #define HSE_VALUE    ((uint32_t) 12000000 ) /*!< Value of the External oscillator in Hz */ #endif /* STM32F10X_CL */ #endif /* HSE_VALUE */ //微信公众号:玩转嵌入式,ID:micropoint8 3.依然无效 不过很奇怪的是,即使修改了此处的值,PLL的时钟还是不正确(PLL按9倍频配置)。 4.PLL时钟配置 顺着代码寻找原因,最后发现真正起作用的部分在 system_stm32f10x.c里的 SetSysClockTo72(void)函数(0993行,这里假设我们希望MCU工作在72MHZ)。 在1058行有这样一段代码: #else /*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |                                         RCC_CFGR_PLLMULL));     RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6); 注释部分是函数自带的,真正起作用的部分在这里,因此把RCC_CFGR_PLLMULL9改为 RCC_CFGR_PLLMULL6。 至此,STM32可正常输出PLL时钟频率。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-01-20 关键词: 晶振 STM32 单片机

  • C语言编程建议和技巧,同样适用于单片机的学习

    1、排版问题 指针也需要合理的符号。np 仅仅只是作为指针 nodepointer 的助记符。如果一贯都遵从命名规范,那么很容易就能推断出 np 表示“节点指针”。在下一篇文章中会提到更多。 同时在编程可读性的其它方面,一致性也是极其重要的。假使变量名为 maxphysaddr,则不要给同级关系的变量取名 lowestaddress。 最后,我倾向于「最小长度」但「最大信息量」的命名,并让上下文补齐其余部分。例如:全局变量在使用时很少有上下文帮助理解,那么它们的命名相对而言更需要令人易懂。因此我称 maxphyaddr 作为一个全局变量名,对于在本地定义和使用的指针来说 np 并不一定是 NodePoint。这是品味的问题,但品味又与清晰度相关。 我避免在命名时嵌入大写字母;它们的阅读舒适性太别扭了,像糟糕的排版一样令人心烦。 3、指针的使用 C语言不同寻常,因为它允许指针指向任何事物。指针是锋利的工具,像任何这样的工具一样,使用得当可以产生令人愉悦的生产力,但使用不当也可以造成极大的破坏。指针在学术界的名声不太好,因为它太危险了,莫名其妙地就变得糟糕的不行。但我认为它是强大的符号,它可以帮助我们清楚地自我表达。 思考:当有指针指向对象时,对于那个对象,确切地说它只是名称,其它什么也不是。听起来很琐碎,但看看下面的两个表达式: 第一个指向一个 node(节点),第二个计算为(可以说)同一个 node。但第二种形式是不太容易理解的表达式。这里解释一下,因为我们必须要知道 node 是什么,i 是什么,还要知道 i 和 node 与周围程序之间相关的规则是什么。孤立的表达式并不能说明 i 是 node 的有效索引,更不用提是我们想要元素的索引。 如果 i、j 和 k 都是 node 数组中的索引将很容易出差错,而且连编译器都不能帮助找出错误。当给子程序传参数时,尤其容易出错:指针只是一个单独的参数;但在接收的子程序中必须认为数组和索引是一体的。 计算为对象表达式本身,比该对象的地址更不易察觉,而且容易出错。正确使用指针可以简化代码: vs. 如果想取下一个元素的 type 可以是 或 i 前移,但其余的表达式必须保持不变;用指针的话,只需要做一件事,就是指针前移。 把排版因素也考虑进来。对于处理连续的结构体来说,使用指针比用表达式可读性更好:只需要较少的笔墨,而且编译器和计算机的性能消耗也很小。与此相关的问题是,指针类型会影响指针正确使用,这也就允许在编译阶段使用一些有用的错误检测,来检查数组序列不能分开。而且如果是结构体,那么它们的标签字段就是其类型的提示。因此 是足以让人明白的。如果是索引数组,数组将取一些精心挑选的名字,而且表达式也会变得更长: 此外,由于例子变得越来越大,额外的字符更加让人恼火。 一般来说,如果发现代码中包含许多相似并复杂的表达式,而且表达式计算为数据结构中的元素,那么明智地使用指针可以消除这些问题。考虑一下 看起来像利用复合表达式表示 p。有时这值得用一个临时变量(这里的 p)或者把运算提取成一个宏。 4、过程名称 过程名称应该表明它们是做什么的,函数名称应该表明它们返回什么。函数通常在像 if 这样的表达式使用,因此可读性要好。 是没有太大帮助的,因为不能推断出 checksize 错误时返回 true,还是非错误时返回。相反 使这点能清晰表达,并且在常规使用中将来也不大可能出错。 5、注释 这一个微妙的问题,需要自己体会和判断。由于一些原因,我倾向于宁可清除注释。第一,假如代码清晰,并且使用了规范的类型名称和变量名称,应该从代码本身就可以理解。第二,编译器不能检查注释,因此不能保证准确,特别是代码修改过以后。误导性的注释会非常令人困惑。第三,排版问题:注释会使代码变得杂乱。 但有时我会写注释,像下文一样仅仅只是把它们用于介绍。例如:解释全局变量的使用和类型(我总是在庞大的程序中写注释);作为一个不寻常或者关键过程的介绍;或标记出大规模计算的一节。 有一个糟糕注释风格的例子: 还有更糟糕的做法: 先不要嘲笑,等到在现实中看到再去吧。 或许除了诸如重要数据结构的声明(对数据的注释通常比对算法的更有帮助),这样至关重要部分之外,需要避免对注释的“可爱”排版和大段的注释;基本上最好就不要写注释。如果代码需要靠注释来说明,那最好的方法是重写代码,以便能更容易地理解。这就把我们带到了复杂度。 6、复杂度 许多程序过于复杂,比需要有效解决的问题更加复杂。这是为什么呢?大部分是由于设计不好,但我会跳过这个问题,因为这个问题太大了。然而程序往往在微观层面就很复杂,有关这些可以在这里解决。 规则 1:不要断定程序会在什么地方耗费运行时间。瓶颈总是出现在令人意想不到的地方,直到证实瓶颈在哪,不要试图再次猜测并加快运行速度。 规则 2:估量(measure) 在没有对代码做出估量之前不要优化速度,除非发现最耗时的那部分代码,要不也不要去做。 规则 3:当 n 很小时(通常也很小),花哨的算法运行很慢。花哨算法有很大的常数级别复杂度。在你确定 n 总是很大之前, 不要使用花哨算法。(即使假如 n 变大,也优先使用规则 2).例如,对于常见问题,二叉树总比伸展树高效。 规则 4:花哨的算法比简单的算法更容易有 bug,而且实现起来也更困难 尽量使用简单的算法与简单的数据结构。 以下几乎是所有实际程序中用到的数据结构: 数组 链表 哈希表 二叉树 当然也必须要有把这些数据结构灵活结合的准备,比如用哈希表实现的符号表,其中哈希表是由字符型数组组成的链表。 规则 5:以数据为核心 如果选择了适当的数据结构并把一切都组织得很有条理性,算法总是不言而喻的。编程的核心是数据结构,而不是算法。(参考 Brooks p. 102) 规则 6:就是没有规则 6。 7、数据编程 有人认为,现在是java和.net的时代,有谁还需要C以及汇编呢?孰不知,java和.net是建立在软件之上的,是为了垄断市场而建立起来的体系, 犹如挖好一个金壁辉煌的坑,请你往下跳,还自以为站在巨人的肩膀上,事实上成了坑底之蛙。要成为一个真正的程序员,并期望成为一个程序员高手,必须从机器 出发,从cpu到操作系统,再到软件体系,高手的境界就是悟道后的明镜灵台,软件设计出神入化,我就是程序,程序就是我。 旁观者李四说:此人大笨也!我用鼠标随便拖几个控件,就是一个xxx管理系统了,你用C语言怕是一年也写不出来吧!好吧,我要承认,讲这话的都已经是mS 的奴才了,别的我不了解,MFC本身就是一个封闭的架构,从MFC入手学习,你只会形成一种封闭的思维模式,因为MS希望很多人只学会表面的东西,不致成 为高手,所以它大力推荐所谓的可视化的程序开发工具,也真有很多人愿意上他的当,最后真正迷失方向。说他坐不了程序吧,他也可以作,但是如果程序复杂一 点,出现问题时,问题出再哪里就搞不清楚了,反正是不清楚! 梁肇新,大牛啊,他说:"我就搞不懂了,用鼠标怎么写程序呢?在我的公司里,高手的键盘响个不停,鼠标偶尔响一下,新手是鼠标响个不停,键盘偶尔响一下,他们的薪水相差的就不是一倍那么多了!" C语言是各大操作系统的基础,Unix、Linux、Windows其内核都清一色是C语言开发的,(某些地方是和汇编语言混合开发的),君不见 WindowsAPI都是C语言函数的接口?Unix/Linux绝大多数应用都是C语言开发的;Windows应用程序用纯API开发已然不多,大多都 是依靠某种ApplicationFramework,比如所谓的VC++,其实就是指VCIDE+C++语言+MFC(现在重点已转向ATL、 WTL),但是Windows服务、网络、驱动程序等底层软件,还是C语言开发的。各种语言的编译器,包括java虚拟机,都是用C语言开发的。各种嵌入 式设备,如手机、PDA也都是C语言开发的。 下面是一些个人建议: 多看课本、代码 由于C语言灵活、强大,初学者要全面地掌握它非常吃力,因此在学习C语言的过程中,要多看课本、代码,课本上没有的可以上网搜索。首先一定要熟练掌握变量、常量、基本数据类型、库函数及特点和运用、运算符、表达式及语句、C语言编写的基本格式。再次要掌握C语言的流程控制语句、数组、函数、指针等基础知识,上述知识熟练后就可以学习链表、队列、树、图等知识。最后要熟练各个知识点的运用,可以把学习的重点放在函数的设计框架、参数设计、返回值设计等关键问题上。 学好数学、英语 计算机专业的大部分课程都是通过实践来检验学习成果的,更重要的是要将所学的理论知识都要在实践中更好的发挥。编程序是个实干的活,光说不练不行。刚开始学的时候可以多练习书上的习题。对于自己不明白的地方,自己编个小程序实验一下是最好的方法,能给自己留下深刻的印象。自己动手的过程中要不断纠正自己不好的编程习惯和认识错误 C语言也是一门实践性很强的课程,既要掌握概念,又要动手编程、上机调试运行。养成上机前分析题目,并编出程序源代码的好习惯,编程时要注意程序的格式、标点符号等,同时调试程序时要有耐心,有时一个程序可能要修改多次,甚至于费了不少劲还是没结果。要不断向老师或者同学请教,不断地查阅资料,所以编程千万不可遇难而退,这个时候是决定你水平提高的关键,一定要坚持到底。大家对自己要有自信,对学好C语言课程要有信心,这样我们才会有一个好的学习状态并改正BUG。程序调试成功后,要总结分析出自己在编写程序时都出现了那些不足,在以后的解题过程中自己应该注意的问题。上机调式程序成功后要完成实验报告,逐步积累调试程序的经验。培养自己良好的编程习惯。 养成良好的编程习惯 (1)在比较复杂的代码后面要有注释。如果光溜溜一堆代码,别人就不可能看懂你的代码,而且也不利于查找错误。除非你一直编东西给自己看。能在代码里说明白的就一定要在代码里体现。比如变量名、函数名,在命名的时候尽量说明是干什么用的。 (2)注意语句的嵌套不要太长,把主函数尽量写简短。经常看到别人的代码是主函数只有几行,几个函数调用,而定义全在主函数外部。这样一是减少了主函数内部的嵌套,二是比较精简,容易读懂。 (3)注意语句的选择。并不是分支语句就用if循环就用while、for。在适当的情况下switch和dowhile语句也是要用的。在某些时候,switch语句比if语句更加精练明了,而dowhile比while少一个循环。 很多想学单片机的人问我的第一句话就是怎样才能学好单片机?对于这个问题我今天就我自己是如何开始学单片机,如何开始上手,如何开始熟练这个过程给大家讲讲。 先说说单片机,一般我们现在用的比较多的的MCS-51的单片机,它的资料比较多,用的人也很多,市场也很大。就我个人的体会怎么样才能更快的学会单片机这门课。单片机这门课是一项非常重视动手实践的科目,不能总是看书,但是学习它首先必须得看书,因为从书中你需要大概了解一下,单片机的各个功能寄存器,而说明白点,我们使用单片机就是用软件去控制单片机的各个功能寄存器,再说明白点,就是控制单片机那些管脚的电平什么时候输出高,什么时候输出低。由这些高低电平的变化来控制你的系统板,实现我们需要的各个功能。至于看书,只需大概了解单片机各管脚都是干什么的?能实现什么样的功能?第一次,第二次你可能看不明白,但这不要紧,因为还缺少实际的感观认识。所以我总是说,学单片机看书看两三天的就够了,看小说你一天能看五六本,看单片机你两三天看两三遍就够了,可以不用仔细的看。推荐一本书,就这一本就足够,书名是《新编MCS-51单片机应用设计》,是哈尔滨工业大学出版社出的的,作者是张毅刚。大概了解一下书上的内容,然后实践,这是非常关键的,如果说学单片机你不实践那是不可能学会的,关于实践有两种方法你可以选择,一种方法:你自己花钱买一块单片机的学习板,不要求功能太全的,对于初学者来说你买功能非常多的那种板子,上面有很多东西你这辈子都用不着,我建议有流水灯、数码管、独立键盘、矩阵键盘、AD或DA(原理一样)、液晶、蜂鸣器,这就差不多了。如果上面我提到的这些,你能熟练应用,那可以说对于单片机方面的硬件你已经入门了,剩下的就是自己练习设计电路,不断的积累经验。只要过了第一关,后面的路就好走多了,万事开头难,大家可能都听过。方法二:你身边如果有单片机方面的高手,向他求助,让他帮你搭个简单的最小系统板。对于高手来说,做个单片机的最小系统板只需要一分钟的时间,而对于初学者可就难多了,因为只有对硬件了解了,才能熟练运用。而如果你身边没有这样的高手,又找不到可以帮助你的人,那我劝你最好是自己买上一块,毕竟自己有一块要方便的多,以后做单片机类的小实验时都能用得上,还省事。 有了单片机学习板之后你就要多练习,最好是自己有台电脑,一天少看电影,少打游戏,把学习板和电脑连好,打开调试软件坐在电脑前,先学会怎么用调试软件,然后从最简单的流水灯实验做起,等你能让那八个流水灯按照你的意愿随意流动时你已经入门了,你会发现单片机是多么迷人的东西啊,太好玩了,这不是在学习知识,而是在玩,当你编写的程序按你的意愿实现时你比做什么事都开心,你会上瘾的,真的。做电子类的人真的会上瘾。然后让数码管亮起来,这两项会了后,你已经不能自拔了,你已经开始考虑你这辈子要走哪一行了。就是要这样练习,在写程序的时候你肯定会遇到很多问题,而这时你再去翻书找,或是问别人,当得到解答后你会记住一辈子的,知识必须用于现实生活中,解决实际问题,这样才能发挥它的作用,你自己好好想想,上了这么多年大学,天天上课,你在课堂上学到了什么?是不是为了期末考试而忙碌呢?考完得了90分,哈哈哈好高兴啊,下学期开学回来忘的一干二净,是不是?你学到什么了?但是我告诉你单片机一旦学会,永远不会忘了。另外我再说说用汇编和C语言编程的问题。很多同学大一二就开设了C语言的课,我也上过,我知道那时天天就是几乘几,几加几啊,求个阶乘啊。学完了有什么用?让你用C语言编单片机的程序你是不是就傻了?书上的东西我们必须要会运用。单片机编程用C语言或汇编语言都可以,但是我建议用C语言比较好,如果原来有C语言的基础那学起来会更好,如果没有,也可以边学单片机边学C语言,C语言也挺简单,只是一门工具而已,我劝你最好学会,将来肯定用得着,要不你以后也得学,你一点汇编都不会根本无所谓,但你一点C语言都不会那你将来会吃苦头。汇编写程序代码效率高,但相对难度较大,而且很罗嗦,尤其是遇到算法方面的问题时,根本是麻烦的不得了,现在单片机的主频在不断的提高,我们完全不需要那么高效率的代码,因为有高频率的时钟,单片机的ROM也在不断的提高,足够装得下你用C语言写的任何代码,C语言的资料又多又好找,将来可移植性非常好,只需要变一个IO口写个温度传感器的程序在哪里都能用,所以我劝大家用C语言。 总结上面,只要你有信心,做事能坚持到底,有不成功不放弃的强烈意志,那学个单片机来说就是件非常容易的事。 步骤: 1.找本书大概了解一下单片机结构,大概了解就行。不用都看懂,又不让你出书的。(三天) 3.自己网上找些小电路类的资料练习设计外围电路。焊好后自己调试,熟悉过程。(十天) 很多人说,学单片机最好先学汇编语言,以我的经验告诉大家,绝对没有这个必要,初学者一开始就直接用C语言为单片机编程,既省时间,学起来又容易,进步速度会很快。在刚开始学单片机的时候,千万不要为了解单片机内部结构而浪费时间,这样只能打击你的信心,当你学会编程后,自然一步步就掌握其内部结构了。 单片机的学习实践 单片机提高重在实践,想要学好单片机,软件编程必不可少。但是熟悉硬件对于学好单片机的也是非常重要的。如何学习好硬件,动手实践是必不可少的。我们可以通过自己动手做一个自己的电子制作,通过完成它,以提高我的对一些芯片的了解和熟练运用它。这样我们就可以多一些了解芯片的结构。我相信,你完成了一个属于自己的电子制作,你的单片机水平就会有一个质的提高。 这就是我学习单片机的心得体会,希望给单片机的爱好者学好单片机有所帮助。 使用单片机就是理解单片机硬件结构,以及内部资源的应用,在汇编或C语言中学会各种功能的初始化设置,以及实现各种功能的程序编制。 第一步:数字I/O的使用 使用按钮输入信号,发光二极管显示输出电平,就可以学习引脚的数字I/O功能,在按下某个按钮后,某发光二极管发亮,这就是数字电路中组合逻辑的功能,虽然很简单,但是可以学习一般的单片机编程思想,例如,必须设置很多寄存器对引脚进行初始化处理,才能使引脚具备有数字输入和输出输出功能。每使用单片机的一个功能,就要对控制该功能的寄存器进行设置,这就是单片机编程的特点,千万不要怕麻烦,所有的单片机都是这样。 第二步:定时器的使用 学会定时器的使用,就可以用单片机实现时序电路,时序电路的功能是强大的,在工业、家用电气设备的控制中有很多应用,例如,可以用单片机实 现一个具有一个按钮的楼道灯开关,该开关在按钮按下一次后,灯亮3分钟后自动灭,当按钮连续按下两次后,灯常亮不灭,当按钮按下时间超过2s,则灯灭。数 字集成电路可以实现时序电路,可编程逻辑器件(PLD)可以实现时序电路,可编程控制器(PLC)也可以实现时序电路,但是只有单片机实现起来最简单,成本最低。定时器的使用是非常重要的,逻辑加时间控制是单片机使用的基础。 第三步:中断 单片机的特点是一段程序反复执行,程序中的每个指令的执行都需要一定的执行时间,如果程序没有执行到某指令,则该指令的动作就不会发生,这样就会耽误很多快速发生的事情,例如,按钮按下时的下降沿。要使单片机在程序正常运行过程中,对快速动作做出反应,就必须使用单片机的中断功能,该功能就是在快速动作发生后,单片机中断正常运行的程序,处理快速发生的动作,处理完成后,在返回执行正常的程序微信公众号玩转嵌入式。中断功能使用中的困难是需要精确地知道什么时候不允许中断发生(屏蔽中断)、什么时候允许中断发生(开中断),需要设置哪些寄存器才能使某种中断起作用,中断开始时,程序应该干什么,中断完成后,程序应该干什么等等。中断学会后,就可以编制更复杂结构的程序,这样的程序可以干着一件事,监视着一件事,一旦监视的事情发生,就中断正在干的事情,处理监视的事情,当然也可以监视多个事情,形象的比喻,中断功能使单片机具有吃着碗里的,看着锅里的功能。 以上三步学会,就相当于降龙十八掌武功,会了三掌了,可以勉强护身。 第四步:与PC机进行RS232通信 单片机都有USART接口,特别是MSP430系列中很多型号,都具有两个USART接口。USART接口不能直接与PC机的RS232接口连接,它们之间的逻辑电平不同,需要使用一个MAX3232芯片进行电平转换。 USART接口的使用是非常重要的,通过该接口,可以使单片机与PC机之间交换信息,虽然RS232通信并不先进,但是对于接口的学习是非常重要的。正确使用USART接口,需要学习通信协议,PC机的RS232接口编程等等知识。试想,单片机实验板上的数据显示在PC机监视器上,而PC机的键盘信号可以在单片机实验板上得到显示,将是多么有意思的事情啊! 第五步:学会A/D转换 MAP430单片机带有多通道12位A/D转换器,通过这些A/D转换器可以使单片机操作模拟量,显示和检测电压、电流等信号。学习时注意模拟地与数字地、参考电压、采样时间,转换速率,转换误差等概念。使用A/D转换功能的简单的例子是设计一个电压表。 第六步:学会PCI、I2C接口和液晶显示器接口 这些接口的使用可以使单片机更容易连接外部设备,在扩展单片机功能方面非常重要。 第七步:学会比较、捕捉、PWM功能 这些功能可以使单片机能够控制电机,检测转速信号,实现电机调速器等控制起功能。如果以上七步都学会,就可以设计一般的应用系统,相当于学会十招降龙十八掌,可以出手攻击了。 第八步:学习USB接口、TCP/IP接口、各种工业总线的硬件与软件设计 学习USB接口、TCP/IP接口、各种工业总线的硬件与软件设计是非常重要的,因为这是当前产品开发的发展方向。 到此为止,相当于学会15招降龙十八掌,但还不到打遍天下无敌手的境界。即使如此,也算是单片机大虾了! 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-01-20 关键词: 编程 C语言 单片机

  • 怎样才能学好单片机?懂方法、有规划,才能快速进阶

    很多想学单片机的人问我的第一句话就是:怎样才能学好单片机? 对于这个问题我今天就我自己是如何开始学单片机,如何开始上手,如何开始熟练这个过程给大家讲讲。 先说说单片机,在学校时单片机入门用的比较多的是51单片机,资料比较多,用的人也多。就我个人的体会怎么样才能更快的学会单片机这门课。 单片机这门课是一项非常重视动手实践的科目,不能总是看书,但是学习它首先必须得看书,因为从书中你需要大概了解一下,单片机的各个功能寄存器,我们使用单片机就是用软件去控制单片机的各个功能寄存器,就是控制单片机的管脚什么时候输出高电平,什么时候输出低电平。 由这些高低电平的变化来控制你的系统板,实现我们需要的各个功能。至于看书,只需大概了解单片机各管脚都是干什么的?能实现什么样的功能?第一次,第二次你可能看不明白,但这不要紧,因为还缺少实际的感观认识。 所以我总是说,学单片机看书看两三天的就够了,可以不用仔细的看。推荐一本书,就这一本就足够,书名是《新编MCS-51单片机应用设计》,是哈尔滨工业大学出版社出的的,作者是张毅刚。大概了解一下书上的内容,然后实践,这是非常关键的。 学单片机不实践那是不可能学会的,关于实践有两种方法你可以选择,一种方法:你自己花钱买一块单片机的学习板,不要求功能太全的,对于初学者来说你买功能非常多的那种板子,上面有很多东西你这辈子都用不着,我建议有流水灯、数码管、独立键盘、矩阵键盘、AD或DA(原理一样)、液晶、蜂鸣器,这就差不多了。如果上面我提到的这些,你能熟练应用,那可以说对于单片机方面的硬件你已经入门了,剩下的就是自己练习设计电路,不断的积累经验。 只要过了第一关,后面的路就好走多了,万事开头难,大家可能都听过。方法二:你身边如果有单片机方面的高手,向他求助,让他帮你搭个简单的最小系统板。 对于高手来说,做个单片机的最小系统板只需要一分钟的时间,而对于初学者可就难多了,因为只有对硬件了解了,才能熟练运用。而如果你身边没有这样的高手,又找不到可以帮助你的人,那我劝你最好是自己买上一块,毕竟自己有一块要方便的多,以后做单片机类的小实验时都能用得上,还省事。 有了单片机学习板之后你就要多练习,最好是自己有台电脑,一天少看电影,少打游戏,把学习板和电脑连好,打开调试软件坐在电脑前,先学会怎么用调试软件,然后从最简单的流水灯实验做起,等你能让那八个流水灯按照你的意愿随意流动时你已经入门了,你会发现单片机是多么迷人的东西啊,太好玩了,这不是在学习知识,而是在玩,当你编写的程序按你的意愿实现时你比做什么事都开心,你会上瘾的,真的。 可以在下面的搜索框中搜索您需要的内容。 做电子类的人真的会上瘾。然后让数码管亮起来,这两项会了后,你已经不能自拔了,你已经开始考虑你这辈子要走哪一行了。 就是要这样练习,在写程序的时候你肯定会遇到很多问题,而这时你再去翻书找,或是问别人,当得到解答后你会记住一辈子的,知识必须用于现实生活中,解决实际问题,这样才能发挥它的作用,你自己好好想想,上了这么多年大学,天天上课,你在课堂上学到了什么? 是不是为了期末考试而忙碌呢?考完得了90分,哈哈哈好高兴啊,下学期开学回来忘的一干二净,是不是?你学到什么了?但是我告诉你单片机一旦学会,永远不会忘了。另外我再说说用汇编和C语言编程的问题。很多同学大一二就开设了C语言的课,我也上过,我知道那时天天就是几乘几,几加几啊,求个阶乘啊。 学完了有什么用?让你用C语言编单片机的程序你是不是就傻了?书上的东西我们必须要会运用。单片机编程用C语言或汇编语言都可以,但是我建议用C语言比较好,如果原来有C语言的基础那学起来会更好,如果没有,也可以边学单片机边学C语言,C语言也挺简单,只是一门工具而已,我劝你最好学会,将来肯定用得着,要不你以后也得学,你一点汇编都不会根本无所谓,但你一点C语言都不会那你将来会吃苦头。 汇编写程序代码效率高,但相对难度较大,而且很罗嗦,尤其是遇到算法方面的问题时,根本是麻烦的不得了,现在单片机的主频在不断的提高,我们完全不需要那么高效率的代码,因为有高频率的时钟,单片机的ROM也在不断的提高,足够装得下你用C语言写的任何代码,C语言的资料又多又好找,将来可移植性非常好,只需要变一个IO口写个温度传感器的程序在哪里都能用,所以我劝大家用C语言。 总结上面,只要你有信心,做事能坚持到底,有不成功不放弃的强烈意志,那学个单片机来说就是件非常容易的事。 步骤 1.找本书大概了解一下单片机结构,大概了解就行。不用都看懂,又不让你出书的。(3天) 2.找学习板练习编写程序,学单片机就是练编程序,遇到不会的再问人或查书。 (20天) 3.自己网上找些小电路类的资料练习设计外围电路。焊好后自己调试,熟悉过程。 (10天) 4.自己完全设计具有个人风格的电路、产品,你已经是高手了。 看到了吗?下功夫一个多月你就能成为高手,我就讲这么多了,学不学得会,下不下得了功夫就看你的了。 我的单片机学习心得 很多人说,学单片机最好先学汇编语言,以我的经验告诉大家,绝对没有这个必要,初学者一开始就直接用C语言为单片机编程,既省时间,学起来又容易,进步速度会很快。在刚开始学单片机的时候,千万不要为了解单片机内部结构而浪费时间,这样只能打击你的信心,当你学会编程后,自然一步步就掌握其内部结构了。 单片机的学习实践 单片机提高重在实践,想要学好单片机,软件编程必不可少。但是熟悉硬件对于学好单片机的也是非常重要的。 如何学习好硬件,动手实践是必不可少的。我们可以通过自己动手做一个自己的电子制作,通过完成它,以提高我的对一些芯片的了解和熟练运用它。这样我们就可以多一些了解芯片的结构。我相信,你完成了一个属于自己的电子制作,你的单片机水平就会有一个质的提高。 这就是我学习单片机的心得体会,希望给单片机的爱好者学好单片机有所帮助。 使用单片机就是理解单片机硬件结构,以及内部资源的应用,在汇编或C语言中学会各种功能的初始化设置,以及实现各种功能的程序编制。 第一步:数字I/O的使用 使用按钮输入信号,发光二极管显示输出电平,就可以学习引脚的数字I/O功能,在按下某个按钮后,某发光二极管发亮,这就是数字电路中组合逻辑的功能,虽然很简单,但是可以学习一般的单片机编程思想,例如,必须设置很多寄存器对引脚进行初始化处理,才能使引脚具备有数字输入和输出输出功能。每使用单片机的一个功能,就要对控制该功能的寄存器进行设置,这就是单片机编程的特点,千万不要怕麻烦,所有的单片机都是这样。 第二步:定时器的使用 学会定时器的使用,就可以用单片机实现时序电路,时序电路的功能是强大的,在工业、家用电气设备的控制中有很多应用,例如,可以用单片机实 现一个具有一个按钮的楼道灯开关,该开关在按钮按下一次后,灯亮3分钟后自动灭,当按钮连续按下两次后,灯常亮不灭,当按钮按下时间超过2s,则灯灭。 数字集成电路可以实现时序电路,可编程逻辑器件(PLD)可以实现时序电路,可编程控制器(PLC)也可以实现时序电路,但是只有单片机实现起来最简单,成本最低。定时器的使用是非常重要的,逻辑加时间控制是单片机使用的基础。 第三步:中断 单片机的特点是一段程序反复执行,程序中的每个指令的执行都需要一定的执行时间,如果程序没有执行到某指令,则该指令的动作就不会发生,这样就会耽误很多快速发生的事情,例如,按钮按下时的下降沿。 要使单片机在程序正常运行过程中,对快速动作做出反应,就必须使用单片机的中断功能,该功能就是在快速动作发生后,单片机中断正常运行的程序,处理快速发生的动作,处理完成后,在返回执行正常的程序。 中断功能使用中的困难是需要精确地知道什么时候不允许中断发生(屏蔽中断)、什么时候允许中断发生(开中断),需要设置哪些寄存器才能使某种中断起作用,中断开始时,程序应该干什么,中断完成后,程序应该干什么等等。 中断学会后,就可以编制更复杂结构的程序,这样的程序可以干着一件事,监视着一件事,一旦监视的事情发生,就中断正在干的事情,处理监视的事情,当然也可以监视多个事情,形象的比喻,中断功能使单片机具有吃着碗里的,看着锅里的功能。 以上三步学会,就相当于降龙十八掌武功,会了三掌了,可以勉强护身。 第四步:与PC机进行RS232通信 单片机都有USART接口,特别是MSP430系列中很多型号,都具有两个USART接口。USART接口不能直接与PC机的RS232接口连接,它们之间的逻辑电平不同,需要使用一个MAX3232芯片进行电平转换。 USART接口的使用是非常重要的,通过该接口,可以使单片机与PC机之间交换信息,虽然RS232通信并不先进,但是对于接口的学习是非常重要的。正确使用USART接口,需要学习通信协议,PC机的RS232接口编程等等知识。试想,单片机实验板上的数据显示在PC机监视器上,而PC机的键盘信号可以在单片机实验板上得到显示,将是多么有意思的事情啊! 第五步:学会A/D转换 MAP430单片机带有多通道12位A/D转换器,通过这些A/D转换器可以使单片机操作模拟量,显示和检测电压、电流等信号。学习时注意模拟地与数字地、参考电压、采样时间,转换速率,转换误差等概念。使用A/D转换功能的简单的例子是设计一个电压表。 第六步:学会PCI、I2C接口和液晶显示器接口 这些接口的使用可以使单片机更容易连接外部设备,在扩展单片机功能方面非常重要。 第七步:学会比较、捕捉、PWM功能 这些功能可以使单片机能够控制电机,检测转速信号,实现电机调速器等控制起功能。如果以上七步都学会,就可以设计一般的应用系统,相当于学会十招降龙十八掌,可以出手攻击了。 第八步:学习USB接口、TCP/IP接口、各种工业总线的硬件与软件设计。 学习USB接口、TCP/IP接口、各种工业总线的硬件与软件设计是非常重要的,因为这是当前产品开发的发展方向。 到此为止,相当于学会15招降龙十八掌,但还不到打遍天下无敌手的境界。即使如此,也算是单片机大虾了!! 单片机的“超神之路”:三个规划 首先,单片机不是万能的,但没有单片机那是万万不能的。从N年前的单片机,到现在的单片机,单片机只是单片机,其性质并没有太多的改变。只是从原来的“神秘”、“暴利”、“有趣”等等,回归了她原来的真是面目罢了--那只是在说明社会在进步,更加的合理和趋于理性。 只是现在的这样回归,有点走了极端,从一个极端走了另一个极端罢了。但相反,社会在这方面的需求却是越来越大,至少在我们的有生之年,这样的“自动化”过程一直会贯穿下去。所以你有什么好担心的,怕自己没有用武之地吗?!怕自己的资薪没有或不高吗? 我自己在单片机和自己熟悉的行业上做了快10年了,不说自己的水平怎么样。说牛不牛,说不牛也牛--该骄傲的时候还是要骄傲的,那是对自己的肯定,该谦虚的时候也要谦虚学习,毕竟单片机总是一个系统工程,方方面面的东西不是自己都要熟悉和精确把握的。要想自己混的不错,我还是那句话---和自己所处的行业结合,那才是王道。 有些人在抱怨单片机在社会上的方方面面,那只是一个现象或表象罢了,或者说那只是纯电子开发或纯电子开发的配套产品,在面临更加激烈的竞争情况罢了。别说自己只会编编程,做点纯电子的工作就觉得不得了了,那就错了,单片机系统工程没有那么狭隘。 如果你走不出这种狭隘,那你注定就是在抱怨的那部分人。就像我前面说的,单片机只是在回归她的本来面目而已。还有就是中国就是太缺少“到了50、60岁的样子”,都还在从事单片机工作的人。也许那也是新兴的中国需要经历的一个过程吧?! 没有什么职业是最好的,只有在当前或相当一段时间内适合自己的职业。就说单片机,对我来说,单片机的工作成果那只是一个配件(当然纯电子产品除外),正因为是“配件”,所以你需要提供相应的物理尺寸,单片机系统的散热,安装条件和安装方式等等情况,需要与你的上下游提供的环境配合好,而不是说我的单片机功能完成了就没我的事了,万事大吉了。 就仅对单片机需要实现的功能来说,如果你连功能都实现不了,那我还要你做什么--那只是基础工作。其实,往往上下游提供的环境对你的设计就是一种考验,也有你需要变换N种方案才能比较好的实现的可能。很明显,这样的上下游环境,对你就是一种很好的资源,不过有些人可能就会视而不见,让你更加熟悉自己开发的东西,在这个行业中的使用和价值情况,对自己的今后发展都是一个很好的参考。不像C、C++的人员到了没有发挥平台的时候,就很郁闷了。相反,对单片机来说,我们可以为自己建立那样的可以供自己发挥和发展的平台。 说了那么多,我只是在闲聊,聊聊自己的看法,希望对你有点帮助。 就我的理解出发,单片机是相当“底层”和“硬件”的东西,没有太多高深的数据结构,也没有太多需要技巧的编程算法,只要我们从单片机执行的角度去理解和编程就行了。一个单片机就可以构成一个电子系统,也可以只构成一个智能节点。没有太多高深的东西需要去研究,因为我们只是单片机的应用者而已,别把自己提到“研究”的高度,我们只在“应用”的高度。 正因为是在“应用”的高度,所以在熟悉和能精确把握“单片机的使用”的时候,应该把更多的精力放在“单片机的应用”的“使用环境”上。曾经有个牛人,拿着intel的8031的芯片技术手册和内部手册,在一个单片机上实现了你想都没想过能实现的应用,但我认为那个是没有必要的,除非你想搞51芯片开发。说了那么多,如果你还在为单片机而单片机的话,那我觉得你有点可悲了。 多熟悉单片机的上下游环境和条件,那不是很困难的事。我希望自己理解的这些东西,对后来者有点帮助,对新手能够带来点思考的东西,那就够了。 规划高度一: 当有一定的年龄和人力资源后,就可以自己出来做了,当个所谓的半个老板了。但当自己做老板说容易也容易,说不容易也不容易。当初我就是在这样的忐忑中,冲了进去。项目接的很多,周期对自己规定的也很短,往往都是白天在处理前一个或前面项目的维护工作,晚上回来工作到一、二点开发新项目。 累就不用说了,有时想想那是在拿自己的命来搏钱啊!!!老婆不太同意我出来自己干,做的好好的也不错。于是,我就对老婆说,可能我不能每个月准时的拿钱养家糊口,但我保证一年下来的平均每个月养家糊口的钱一定不会低于现在。就这样,我开始了走自己的路了。吃苦受累我不怕,付出了没有收获我不怕。怕的就是过不了自己的心理关,也许一直以来都比较好运气和顺利的缘故吧?!作为和我同行的兄弟姐妹们,一定要过了自己的心理关,别太在意今时今日的得失,还有所谓的某些情况下的“面子”。 至少我们应该用“最小的代价”来给自己当“学费”。也不怕你们笑话,我的“学费”交的也不少。一个成功的项目,不是你的功能有多好,有多强,而是你的开发成功为你的项目方带来了多少的利润收入,那才是真正的成功了,尽管你只赚了点儿开发费。 做项目,别为自己考虑太多,多换位思考一下。人家能信任你,把项目交给你做,你就多该从项目方的角度考虑考虑---也许有时他们的要求有点过分,但所谓不知者不去怪罪了。 规划高度二: 做一个称职的软硬电子工程师吧。不用学太多,就学一些就行了,也不要去跟风,那个没有必要。有时,你就是去学了,如果没有相应对应的开发任务,学的也是皮毛,不过只要皮毛也可以了,当你真正需要的时候,再拿起来就会快很多,也算是一种储备吧。 但你至少要会一种,一种相对来说狭隘的系统吧?!不怕你笑话,我就只会51单片机。先说说我自己了,从事工业自动化方面的机床设备行业: 精通51,了解其他的单片机,精通51汇编,精通CPLD,半精通C51(只用来做点人机界面工作),粗通FPGA(想精通自己做51IP核)。 粗通ARMDSP,粗通ARM和DSP的汇编,了解C编程。 精通三维造型软件SOLIDWORKS(可以为自己的线路板造型和机械设备造型) 粗通机加工大部分的工艺。 精通钣金和焊接。 熟悉数控设备、机床的实现解决方案。 对于每个人来说,学以致用,以前的我什么都想学,什么都用不好,当学的时候,却没有用的发挥平台,都是为学而学。但至少当你要用的时候,重新捡起来的时候,就会很快。就拿ARM来说吧,学的时候学的很努力,从其机理到实现,也做过好多的实验,可现在就是用的少就剩下了点概念的东西了。 所以没必要什么都要精通,只要一样,比如51单片机吧,从设计、投板、采购、焊接、一直到调试成成品等等一个系统下来,如果你思考了,如果你精通了,你还怕什么,不给高工资也要给你高年薪了,应该都能了解“老板一将难求”的道理了。 规划高度三: 做一个合格的新手电子工程师吧。对于新手,我的建议是:别上来就是一个什么五年十年规划之类的,我们都是普通人,那种规划不适合普通人。如果我们能将今后一年和二年的规划做好了,那你就已经很了不起了。 每天都是一个想法,每月都是一个变化,更别说每年了,只要你在努力,脚踏实地的做事。不要把自己搞的太忙碌了,给自己每天留半个小时想想“心事”了。做好一样,再发散开去,对于电子类的,什么ARM,DSP,51都是相通的。精通了一个体系,那么其他电子类的体系都是相通。怕就怕你什么都不通,都是半通。还半桶水的晃来晃去的,那就有点郁闷和悲哀了!  免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-01-20 关键词: 单片机

  • STM32中C语言知识点:初学者必看,老鸟复习(长文总结)

    说在前面的话 一位初学单片机的小伙伴让我推荐C语言书籍,因为C语言基础比较差,想把C语言重新学一遍,再去学单片机,我以前刚学单片机的时候也有这样子的想法。 其实C语言是可以边学单片机边学的,学单片机的一些例程中,遇到不懂的C语言知识,再去查相关的知识点,这样印象才会深刻些。 下面就列出了一些STM32中重要的C语言知识点,初学的小伙伴可以多读几遍,其中大多知识点之前都有写过,这里重新整理一下,更详细地分析解释可以阅读附带的链接。 assert_param 断言(assert)就是用于在代码中捕捉这些假设,可以将断言看作是异常处理的一种高级形式。 断言表示为一些布尔表达式,程序员相信在程序中的某个特定点该表达式值为真。 可以在任何时候启用和禁用断言验证,因此可以在测试时启用断言,而在部署时禁用断言。同样,程序投入运行后,最终用户在遇到问题时可以重新启用断言。 注意assert()是一个宏,而不是函数。 在STM32中,常常会看到类似代码: assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));assert_param(IS_ADC_SINGLE_DIFFERENTIAL(SingleDiff)); 这是用来检查函数传入的参数的有效性。STM32中的assert_param默认是不使用的,即: 如果要使用,需要定义USE_FULL_ASSERT宏,并且需要自己实现assert_failed函数。特别的,使用STM32CubeMX生成代码的话,会在main.c生成: 我们在这进行填充就好。 下面分享一下assert的应用例子: // 公众号:嵌入式大杂烩#include #include  int main(void){ int a, b, c; printf("请输入b, c的值:"); scanf("%d %d", &b, &c); a = b / c; printf("a = %d", a); return 0;} 此处,变量c作为分母是不能等于0,如果我们输入2 0,结果是什么呢?结果是程序会蹦: 这个例子中只有几行代码,我们很快就可以找到程序蹦的原因就是变量c的值为0。但是,如果代码量很大,我们还能这么快的找到问题点吗? 这时候,assert()就派上用场了,以上代码中,我们可以在a = b / c;这句代码之前加上assert(c);这句代码用来判断变量c的有效性。此时,再编译运行,得到的结果为: 可见,程序蹦的同时还会在标准错误流中打印一条错误信息: Assertion failed:c, file hello.c, line 12 这条信息包含了一些对我们查找bug很有帮助的信息:问题出在变量c,在hello.c文件的第12行。这么一来,我们就可以迅速的定位到问题点了。 这时候细心的朋友会发现,上边我们对assert()的介绍中,有这么一句说明: 如果表达式的值为假,assert()宏就会调用_assert函数在标准错误流中打印一条错误信息,并调用abort()(abort()函数的原型在stdlib.h头文件中)函数终止程序。 所以,针对我们这个例子,我们的assert()宏我们也可以用以下代码来代替: if (0 == c){ puts("c的值不能为0,请重新输入!"); abort();} 这样,也可以给我们起到提示的作用: 但是,使用assert()至少有几个好处: 1)能自动标识文件和出问题的行号。 2)无需要更改代码就能开启或关闭assert机制(开不开启关系到程序大小的问题)。如果认为已经排除了程序的bug,就可以把下面的宏定义写在包含assert.h的位置的前面: #define NDEBUG 并重新编译程序,这样编辑器就会禁用工程文件中所有的assert()语句。如果程序又出现问题,可以移除这条#define指令(或把它注释掉),然后重新编译程序,这样就可以重新启用了assert()语句。 相关文章:【C语言笔记】assert()怎么用? 预处理指令 1、#error #error "Please select first the target STM32L4xx device used in your application (in stm32l4xx.h file)" #error 指令让预处理器发出一条错误信息,并且会中断编译过程。 #error的例子: // 公众号:嵌入式大杂烩#include #define  RX_BUF_IDX  100#if RX_BUF_IDX == 0static const unsigned int rtl8139_rx_config = 0;#elif RX_BUF_IDX == 1static const unsigned int rtl8139_rx_config = 1;#elif RX_BUF_IDX == 2static const unsigned int rtl8139_rx_config = 2;#elif RX_BUF_IDX == 3static const unsigned int rtl8139_rx_config = 3;#else#error "Invalid configuration for 8139_RXBUF_IDX"#endifint main(void){ printf("hello world\n"); return 0;} 这段示例代码很简单,当RX_BUF_IDX宏的值不为0~3时,在预处理阶段就会通过#error 指令输出一条错误提示信息: "Invalid configuration for 8139_RXBUF_IDX" 下面编译看一看结果: 2、#if、#elif、#else、#endif、#ifdef、#ifndef (1)#if #if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)  void (* ConvCpltCallback)(struct __ADC_HandleTypeDef *hadc);               // ......#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */ #if的使用一般使用格式如下 #if 整型常量表达式1  程序段1#elif 整型常量表达式2  程序段2#else  程序段3#endif 执行起来就是,如果整形常量表达式为真,则执行程序段1,以此类推,最后#endif是#if的结束标志。 (2)#ifdef、#ifndef #ifdef HAL_RTC_MODULE_ENABLED  #include "stm32l4xx_hal_rtc.h"#endif /* HAL_RTC_MODULE_ENABLED */ #ifdef的作用是判断某个宏是否定义,如果该宏已经定义则执行后面的代码,一般使用格式如下: #ifdef  宏名  程序段1#else  程序段2#endif 它的意思是,如果该宏已被定义过,则对程序段1进行编译,否则对程序段2进行编译,通#if一样,#endif也是#ifdef的结束标志。 #ifndef __STM32L4xx_HAL_ADC_EX_H#define __STM32L4xx_HAL_ADC_EX_H// ......#endif #ifndef的作用与#ifdef的作用相反,用于判断某个宏是否没被定义。 (3)#if defined、#if !defined defined用于判断某个宏是否被定义, !defined与defined的作用相反。这样一来#if defined可以达到与#ifdef一样的效果。如例子: #if defined(STM32L412xx)  #include "stm32l412xx.h"#elif defined(STM32L422xx)  #include "stm32l422xx.h"//........#elif defined(STM32L4S9xx)  #include "stm32l4s9xx.h"#else #error "Please select first the target STM32L4xx device used in your application (in stm32l4xx.h file)"#endif 如果STM32L412xx宏被定义,则包含头文件stm32l412xx.h,以此类推。 既然已经有#ifdef、#ifndef了,#if defined与#if !defined是否是多余的? 不是的,#ifdef和#ifndef仅能一次判断一个宏名,而defined能做到一次判断多个宏名,例如: #if defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)// ......#endif /* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */ 更进一步,可以构建一些更密切地因果处理,如: #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION 

    时间:2021-01-19 关键词: C语言 STM32 单片机

  • 什么?单片机还在裸奔?ESP8266纯串口透传,助力设备上云端

    项目有些久远,前年的机器人上需要的功能,当时是需要将STM32上的数据上传到服务器,比如机器人的速度,行驶距离,是否在拍照等等。便于管理者在PC或者手机上了解机器人的工作状态,同时可以远程下发指令给机器人,控制其完成相应动作。 因为所有的逻辑判断和控制都在服务器或者STM32上面,作为中间的无线模块仅仅需要上传STM32的数据并接收服务器下发的指令即可,所以这里对WiFi模块的要求不高,仅仅需要它作为透传功能即可。当时在选型的时候试过好几款WiFi模块,最终敲定了安信可的ESP8266,价格便宜,开发简单,但是搭建环境是真的不容易,深受其害 。 选择 好模块就该考虑使用AT指令还是使用SDK开发,AT指令固然简单,但是局限性非常大。如果使用AT指令,我那开发控制端的同事估计就要跳脚了,代码里需要写一大堆的AT指令,如果功能改变,指令代码就需要重写,烦不胜烦。 如果使用SDK开发,控制端只需发送简单的数据就行,完全不用考虑其他任何东西,ESP8266完全当做一个中转站,相对应的我的工作就会繁重,但是,我屈服了,选择使用SDK。 于是就有了下面基于NONOS 2.0的ESP8266串口透传。主要有以下几个功能: 纯串口透传,接收MCU串口数据,直接通过MQTT上传到服务器,接收服务器数据下发给MCU。 smartconfig+airkiss配网,随意使用,场景丰富。 最多储存5个WIFI账号和密码,自动寻找网络连接。 按键配网,长按重新配网,前一次WiFi自动储存,添加配网指示灯。 OTA空中升级(待验证) 从程序的入口开始: //程序入口 void ICACHE_FLASH_ATTR user_init(void){ uart_init(115200, 115200); os_delay_us(60000); keyInit(); set_uart_cb(uart_cb); PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12); //GPIO12初始化 GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 0);//低电平 g et_mac();//获取MAC地址 wifi_set_opmode(STATION_MODE); //设置wifi信息存储数量,最大为5个 wifi_station_ap_number_set(2); mqtt_init(); set_wifistate_cb(wifi_connect_cb, wifi_disconnect_cb); } 程序的入口先进行串口初始化和按键的初始化,以及LED的初始化。串口要初始化波特率,按键初始化配网按键,用于短按配网,长按重新配网,LED只要用于判断模块是否进入配网模式以及是否配网完成。 初始化完成后会首先读取MAC地址,该地址是唯一的,每个模块都不一样,用于填充进主题中,便于服务器区分不同设备,用于多台量产设备的使用,在连接MQTT服务器时会自动填充。 每连接一次WiFi都会将WiFi信息保存在模块内部,每次上电都会自动扫描暴露的WiFi,直接连接,就像手机的WIFI连接,目前最大支持五个WiFi信息的保存,超过5个会剔除最早的WiFi信息,通过短按D5(GPIO14)可进入配网模式。 /*** 按键短按回调*/ LOCAL void ICACHE_FLASH_ATTR key1ShortPress(void) { start_smartconfig(smartconfig_cd); INFO("start_smartconfig\n"); } /*** 按键长按回调*/ LOCAL void ICACHE_FLASH_ATTR key1LongPress(void) { start_smartconfig(smartconfig_cd); INFO("start_smartconfig\n"); } /*** 按键初始化*/ LOCAL void ICACHE_FLASH_ATTR keyInit(void) { //设置按键数量 set_key_num(1); //长按、短按的按键回调 key_add(D5, NULL, key1ShortPress); key_add(D5, NULL, key1LongPress); } 由于找不到最新的代码。这里的长按我没做处理,应该是断开WiFi重新进入配网模式, 或者软复位模块,再进入start_smartconfig()函数: /*** 开始Smartconfig配置 * @param cd: Smartconfig状态回调* @retval None*/ void ICACHE_FLASH_ATTR start_smartconfig(smartconfig_cd_t cd) { smartconfig_flag = 1; smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS); //SC_TYPE_ESPTOUCH,SC_TYPE_AIRKISS,SC_TYPE_ESPTOUCH_AIRKISS wifi_station_disconnect(); wifi_set_opmode(STATION_MODE); finish_cd = cd; smartconfig_start(smartconfig_done); os_timer_disarm(&OS_Timer_Wifichange); // 关闭定时器 if(connect_flag == 1){ w_disconnect(); connect_flag = 0; } os_timer_disarm(&OS_Timer_SM); // 关闭定时器 os_timer_setfn(&OS_Timer_SM, (os_timer_func_t *) sm_wait_time, NULL); // 设置定时器 os_timer_arm(&OS_Timer_SM, 1000, 1); // 使能定时器 } smartconfig_set_type();函数可选3个参数:分别是:SC_TYPE_ESPTOUCH、SC_TYPE_AIRKISS和SC_TYPE_ESPTOUCH_AIRKISS 第一个是smartconfig配网(手机APP),第二个是airkiss配网(微信公众号),最后一个两者都可以。进入该函数会调用smartconfig_start();,该函数会调用smartconfig_done()函数进行配网,配网成功后会点亮LED灯。 /*** Smartconfig 状态处理* @param status: 状态* @param *pdata: AP数据* @retval None*/ void ICACHE_FLASH_ATTRsmartconfig_done(sc_status status, void *pdata) { switch (status) { case SC_STATUS_WAIT: INFO("SC_STATUS_WAIT\n"); break; case SC_STATUS_FIND_CHANNEL: INFO("SC_STATUS_FIND_CHANNEL\n"); break; case SC_STATUS_GETTING_SSID_PSWD: INFO("SC_STATUS_GETTING_SSID_PSWD\n"); sc_type *type = pdata; if (*type == SC_TYPE_ESPTOUCH) { INFO("SC_TYPE:SC_TYPE_ESPTOUCH\n"); } else { INFO("SC_TYPE:SC_TYPE_AIRKISS\n"); } break; case SC_STATUS_LINK: INFO("SC_STATUS_LINK\n"); sm_comfig_status = SM_STATUS_GETINFO; struct station_config *sta_conf = pdata; wifi_station_set_config(sta_conf); wifi_station_disconnect(); wifi_station_connect(); break; case SC_STATUS_LINK_OVER: sm_comfig_status = SM_STATUS_FINISH; INFO("SC_STATUS_LINK_OVER\n"); if (pdata != NULL) { //SC_TYPE_ESPTOUCH uint8 phone_ip[4] = { 0 }; os_memcpy(phone_ip, (uint8*) pdata, 4); INFO("Phone ip: %d.%d.%d.%d\n", phone_ip[0], phone_ip[1], phone_ip[2], phone_ip[3]); } else { //SC_TYPE_AIRKISS - support airkiss v2.0 airkiss_start_discover(); } smartconfig_stop(); smartconfig_flag = 0; connect_flag = 0; os_timer_disarm(&OS_Timer_SM); // 关闭定时器 finish_cd(sm_comfig_status); os_timer_arm(&OS_Timer_Wifichange, 3000, 1); // 使能定时器 break; } } /*** WIFI连接回调*/ void wifi_connect_cb(void){ INFO("wifi connect!\r\n"); os_printf("----- WiFi连接成功,打开绿灯---\r\n"); GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 1); MQTT_Connect(&mqttClient); } /*** WIFI断开回调*/ void wifi_disconnect_cb(void){ INFO("wifi disconnect!\r\n"); os_printf("----- WiFi断开,关闭绿灯---\r\n"); GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 0); MQTT_Disconnect(&mqttClient); } 连接MQTT服务器:网络连接成功以后可以开始MQTT的初始化,初始化包涵一系列的连接初始化回调,连接成功或不成功回调,主题订阅发布回调等等。 /*** MQTT初始化*/ void ICACHE_FLASH_ATTR mqtt_init(void) { MQTT_InitConnection(&mqttClient, MQTT_HOST, MQTT_PORT, DEFAULT_SECURITY); MQTT_InitClient(&mqttClient, mac_str, MQTT_USER,MQTT_PASS, MQTT_KEEPALIVE, 1); MQTT_InitLWT(&mqttClient, lwt_topic, LWT_MESSAGE, 0, 0); MQTT_OnConnected(&mqttClient, mqttConnectedCb); MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb); MQTT_OnPublished(&mqttClient, mqttPublishedCb); MQTT_OnData(&mqttClient, mqttDataCb);} void ICACHE_FLASH_ATTRMQTT_InitConnection(MQTT_Client *mqttClient, uint8_t* host, uint32_t port, uint8_t security){ uint32_t temp; INFO("MQTT_InitConnection\r\n"); os_memset(mqttClient, 0, sizeof(MQTT_Client)); temp = os_strlen(host); mqttClient->host = (uint8_t*)os_zalloc(temp + 1); os_strcpy(mqttClient->host, host); mqttClient->host[temp] = 0; mqttClient->port = port; mqttClient->security = security; } void ICACHE_FLASH_ATTRMQTT_InitClient(MQTT_Client *mqttClient, uint8_t* client_id, uint8_t* client_user, uint8_t* client_pass, uint32_t keepAliveTime, uint8_t cleanSession){ uint32_t temp; INFO("MQTT_InitClient\r\n"); os_printf("CD MQTT_InitClient++++++++++++++++++++++\n"); os_memset(&mqttClient->connect_info, 0, sizeof(mqtt_connect_info_t)); temp = os_strlen(client_id); mqttClient->connect_info.client_id = (uint8_t*)os_zalloc(temp + 1); os_strcpy(mqttClient->connect_info.client_id, client_id); mqttClient->connect_info.client_id[temp] = 0; if (client_user) { temp = os_strlen(client_user); mqttClient->connect_info.username = (uint8_t*)os_zalloc(temp + 1); os_strcpy(mqttClient->connect_info.username, client_user); mqttClient->connect_info.username[temp] = 0; } if (client_pass) { temp = os_strlen(client_pass); mqttClient->connect_info.password = (uint8_t*)os_zalloc(temp + 1); os_strcpy(mqttClient->connect_info.password, client_pass); mqttClient->connect_info.password[temp] = 0; } mqttClient->connect_info.keepalive = keepAliveTime; mqttClient->connect_info.clean_session = cleanSession; mqttClient->mqtt_state.in_buffer = (uint8_t *)os_zalloc(MQTT_BUF_SIZE); mqttClient->mqtt_state.in_buffer_length = MQTT_BUF_SIZE; mqttClient->mqtt_state.out_buffer = (uint8_t *)os_zalloc(MQTT_BUF_SIZE); mqttClient->mqtt_state.out_buffer_length = MQTT_BUF_SIZE; mqttClient->mqtt_state.connect_info = &mqttClient->connect_info; mqtt_msg_init(&mqttClient->mqtt_state.mqtt_connection, mqttClient->mqtt_state.out_buffer, mqttClient->mqtt_state.out_buffer_length); QUEUE_Init(&mqttClient->msgQueue, QUEUE_BUFFER_SIZE); system_os_task(MQTT_Task, MQTT_TASK_PRIO, mqtt_procTaskQueue, MQTT_TASK_QUEUE_SIZE); system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)mqttClient); } WiFi连接成功和失败会触发不同的回调函数: /*** MQTT连接回调*/ void mqttConnectedCb(uint32_t *args) { MQTT_Client* client = (MQTT_Client*) args; INFO("MQTT: Connected\r\n"); MQTT_Publish(client, birth_topic, BIRTH_MESSAGE, os_strlen(BIRTH_MESSAGE), 0,0); MQTT_Subscribe(client,ota_topic, 0); if(updata_status_check()){ MQTT_Publish(client, ota_topic, "updata_finish", os_strlen("updata_finish"), 0,0); }} /** * MQTT断开连接回调*/ void mqttDisconnectedCb(uint32_t *args) { MQTT_Client* client = (MQTT_Client*) args; INFO("MQTT: Disconnected\r\n"); } /*** MQTT发布消息回调*/ void mqttPublishedCb(uint32_t *args) { MQTT_Client* client = (MQTT_Client*) args; INFO("MQTT: Published\r\n"); } 串口透传: 当模块的WiFi和MQTT服务器都连接上之后,模块就开始监听串口和服务器的数据,如果串口有数据过来便转发到服务器或者进行OTA升级,如果服务器有指令下发就转发给串口。 /*** MQTT接收数据回调(用于OTA升级和串口透传)*/ void mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t data_len) { char *topicBuf = (char*) os_zalloc(topic_len + 1), *dataBuf = (char*) os_zalloc(data_len + 1); uint8 *pdata = (uint8*)data; uint16 len = data_len; uart0_tx_buffer(pdata, len); //串口输出 MQTT_Client* client = (MQTT_Client*) args; os_memcpy(topicBuf, topic, topic_len); topicBuf[topic_len] = 0; os_memcpy(dataBuf, data, data_len); dataBuf[data_len] = 0; // INFO("Receive topic: %s, data: %s \r\n", topicBuf, dataBuf); //data = {"url"=http://yourdomain.com:9001/ota/} if (os_strcmp(topicBuf, ota_topic) == 0) { char url_data[200]; if(get_josn_str(dataBuf,"url",url_data)){ // INFO("ota_start\n"); ota_upgrade(url_data,ota_finished_callback); } } os_free(topicBuf); os_free(dataBuf); } /*** ota升级回调*/ void ICACHE_FLASH_ATTR ota_finished_callback(void * arg) { struct upgrade_server_info *update = arg; if (update->upgrade_flag == true) { INFO("OTA Success ! rebooting!\n"); system_upgrade_reboot(); } else { INFO("OTA Failed!\n"); } } 其他问题: 连接的服务器地址,端口号等信息需要写在代码里烧录进模块,这些信息在在mqtt_config.h文件中定义。 上电后可以在串口助手看到打印的MAC地址: 按下配网按键(GPIO14接地),进入配网模式,使用APP或者微信公众号将信息发给模块便可联网,联网后自动连接MQTT服务器。 至此连接完成,后续只需要串口发数据给模块,便可在服务器收到信息,服务器下发指令,单片机串口也可以接收到数据。但是要记得订阅主题哦。该透传代码烧录完成可搭配任意MCU的串口使用。非常便捷。由于项目期较远,可能介绍的不是很详细,需要的大大们可以点击阅读原文回帖获取源码。自行查看。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-01-19 关键词: ESP8266 单片机

  • 超详细干货:用PIC单片机做一个MP3音乐播放器

    网站:bbs.21ic.com PIC16F15324开发板是一款小巧的开发板,它板载了LED和KEY 等基本测试单元,可以完成简单的学习和测试目标。为了充分体验和展示PIC16F15324的性能,在原开发板的基础上通过配置I2C接口的OLED屏来显示信息,使用UART来控制MP3音乐模块来播放音频文件,使用KEY选取播放内容,从而构成了一个可以显示中文歌单的MP3播放装置,其整体构成见图1所示。 图1 播放器整体构成 在设计过程中,主要经过3个阶段: 1) 引脚配置阶段 2)  功能程序设计阶段 3) 功能测试阶段 1.      引脚配置 PIC16F15324对于开发工具的限定,这里是使用MPLABX IDE v5.45为开发工具,并添加MCC进行引脚功能的配置,其引脚配置情况如图2所示。 其中,PA0连接OLED屏的数据引脚,PA1连接OLED屏的时钟引脚;PC4连接MP3播放模块的串口接收引脚;PA5连接按键引脚;PC1作为备用引脚,以便调节音量。 图2 引脚功能配置 此外,因程序设计的需要,还选取了延时功能,见图3所示。 图3选取延时功能 在完成了引脚的配置后,点击“Generate”即可生成程序框架及程序。 2.      功能程序设计 1)  显示程序设计 #define OLED_SCLK_Set()   SCL_SetHigh() #define OLED_SDIN_Set()   SDA_SetHigh() 相应的OLED屏初始化函数为: void OLED_Init(void) { Write_IIC_Command(0xAE); //display off Write_IIC_Command(0x20); //Set Memory Addressing Mode Write_IIC_Command(0x10); Write_IIC_Command(0xb0);//Set Page Start Address for Page Addressing Mode,0-7 Write_IIC_Command(0xc8);//Set COM Output Scan Direction Write_IIC_Command(0x00);//---set low column address Write_IIC_Command(0x10);//---set high column address Write_IIC_Command(0x40);//--set start line address Write_IIC_Command(0x81);//--set contrast control register Write_IIC_Command(0xdf); Write_IIC_Command(0xa1);//--set segment re-map 0 to 127 Write_IIC_Command(0xa6);//--set normal display Write_IIC_Command(0xa8);//--set multiplex ratio(1 to 64) Write_IIC_Command(0x3F);// Write_IIC_Command(0xa4);// Write_IIC_Command(0xd3);//-set display offset Write_IIC_Command(0x00);//-not offset Write_IIC_Command(0xd5);//--set display clock divide ratio/oscillator frequency Write_IIC_Command(0xf0);//--set divide ratio Write_IIC_Command(0xd9);//--set pre-charge period Write_IIC_Command(0x22); // Write_IIC_Command(0xda);//--set com pins hardware configuration Write_IIC_Command(0x12); Write_IIC_Command(0xdb);//--set vcomh Write_IIC_Command(0x20);//0x20,0.77xVcc Write_IIC_Command(0x8d);//--set DC-DC enable Write_IIC_Command(0x14);// Write_IIC_Command(0xaf);//--turn on oled panel OLED_Clear(); } 2)  提取字模及歌曲选择 为了实现图4所示的歌曲选择界面,将所用到的汉字字模用字模提取工具提取出来,并构建了小字库。 图4 歌曲选择界面 图5 提取字模 汉字的显示函数为: void OLED_ShowCHinese(unsigned char x,unsigned char y,unsigned char no) { unsigned char t,adder=0; OLED_Set_Pos(x,y); for(t=0;t<16;t++) { OLED_WR_Byte(Hzk[2*no][t],OLED_DATA); adder+=1; } OLED_Set_Pos(x,y+1); for(t=0;t<16;t++) { OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA); adder+=1; } } 本文系21ic论坛网友jinglixixi原创   免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-01-14 关键词: 音乐播放器 PIC 单片机

  • 在STM32价格疯长下,哪些国产32可以替代?

    GD32F103是GD早期的产品,GD32E103和GD32F303是对GD32F103的升级和优化,所以4者是兼容的,虽然内核不同,但是通用外设几乎很少涉及到内核部分,在时间急迫的情况下可以使用ST的库开发。 中科芯(CETC)    雅特力(Artery)   雅特力的AT32F403A/F407/ F413/ F415/F421系列,可批量替换STM32的F030、F303、F103、F107、F072、F401和F411等系列,其产品硬件引脚与STM32 P2P兼容,软件高度兼容,由于内核、SRAM、外设等性能相比STM32大幅度提升,AT32可一颗取代多颗STM32,另外还独有安全性&二次开发功能: security Lib,更宽的工作温度:-40~105度。 航顺(Hangshun)

    时间:2021-01-14 关键词: MCU STM32 单片机

  • 盘点STM32的国产替代者(2)

    昨日,嵌入式ARM一文《 STM32价格疯长下,盘点STM32的国产替代者 》受到了广泛关注。应读者要求,嵌入式ARM将继续介绍能够替代STM32的国产产品。 今日带来能够完美替代STM32的产品是沁恒微电子的CH32F103以及RISC-V内核的CH32V103两款产品。 CH32F1系列是基于32位Cortex-M3内核设计的通用微控制器。片上集成了时钟安全机制、多级电源管理、 通用DMA控制器等。此系列具有 2 路 USB2.0接口、多通道 TouchKey、 12 位 DAC 转换模块,多通道 12 位 ADC、 多组定时器、 CAN 通讯控制器、 I2C/USART/SPI 等丰富的外设资源。 CH32V103则是其在去年上半年推出的RISC-V架构的32位通用MCU微控制器。CH32V103系列是以RISC-V3A处理器为核心的32位通用微控制器,该处理器是基于RISC-V开源指令集设计。片上集成了时钟安全机制、多级电源管理、通用DMA控制器。此系列具有1路USB2.0主机/设备接口、多通道12位ADC转换模块、多通道TouchKey、多组定时器、多路IIC/USART/SPI接口等丰富的外设资源。 多说无益,直接看几个21ic家网友关于这两款开发板的测评: 【CH32F103测评报告】+基于WCH沁恒CH32F103开发板点灯编程 用户:yljon 试验目标:使用WCH沁恒CH32F103开发板点灯编程试验一、搞点资料看看,电路图要搞到 从21ic论坛(bbs.21ic.com/iclist-900-1.html)里找些资料看看,强烈推荐下载那个CH32F103评估板说明及参考应用例程:CH32F103EVT.ZIP 之所以推荐下载这个压缩档,是因为里面有一个非常好的说明文件: 这个说明文件非常棒,介绍了每个目录的内容,为制作这个说明文件的小哥哥点赞!!!电路图在这个压缩档有: 1. LED没有直接连到MCU引脚,需要准备连接导线;2. 烧录调试接口貌似ST-LINK,准备一个高仿ST-LINK烧录器即可; 二、搭建环境,芯片的PACK安装 上面下载的压缩包里就有PACK,Keil.WCH32F1xx_DFP.1.0.0.pack,直接点击安装即可,打开KEIL,在KEIL里看见如下就意味着PACK搞好了。 先选择一下芯片,如下图: 由于我的烧录器是ST-LINK,在配置中选择即可: 选择一下芯片算法,64K滴: 三、搞定代码,点亮屏幕 上述压缩包里就有现成的例子,点灯LED代码直接拿过用,哎呀,这代码风格就是ST的标准啊,无需额外学习,直接上手,哈哈 void GPIO_Toggle_INIT(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);}int main(void){ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); Delay_Init(); GPIO_Toggle_INIT();while(1) { Delay_Ms(500); PAout(0) ^= (1VCC,这样才会从芯片内的出厂固件内存引导启动,这里相当于Arduino的BootLoader的功能。平常的接法是BOOT0-->GND,这是从Flash区运行启动代码,跳过了厂家代码区。2.硬件准备好后,需要软件。下载WCH_ISP_tool(2.8)下载链接. 安装好后,界面如图。 注意要选择CH32F1系列标签,Keil MDK编译器生成的Hex文件,需要再用户程序文件框内选择。 注意可以多试几次,比如插拔USB转串口小板。还有当出现“解除写保护”,需要先点击“解除保护”按钮。之后再点击下载。4.测试UART_Printf串口打印功能 开发板的串口调试功能可以方便的输出一些具体的信息,作为程序运行的重要参考。这里我测试了math.h的正弦函数计算功能。算是发挥一下32位CPU的优势。想起来计算氢弹的理论的501机,每秒不过几十万次加法运算。这个机子已经远远超过了当年的庞然大物。 测试的源码: main.c int main(void){ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); Delay_Init(); USART_Printf_Init(115200); /* printf using USART1 */printf("SystemClk:%d\r\n",SystemCoreClock);printf("This is printf example\r\n");printf("sin(pi/3)=%f",sin(PI/3));while(1) { }} 使用串口助手来接收信息。 附阅读材料:中国计算机60年国产计算机前史 【RISC-V MCU CH32V103测评】01:LED Demo 用户:740071911 第一次体验risc-v的板子,真的是不错,快递也很迅速。而且cortex m系列挺像的,这样上手就很容易了,体验一下点灯操作。点灯需要注意的是,led小灯没有连接到mcu的引脚上,需要自己用杜邦线连接一下 代码也很简单,有stm32经验的很容易 /********************************** (C) COPYRIGHT ******************************** File Name : main.c* Author : WCH* Version : V1.0.0* Date : 2020/04/30* Description : Main program body.*******************************************************************************/#include "debug.h"void LED_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);}void GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin){ GPIOx->OUTDR ^= GPIO_Pin;}int main(void){ Delay_Init(); //USART_Printf_Init(115200); //printf("SystemClk:%d\r\n",SystemCoreClock); LED_Init(); while(1) { Delay_Ms(1000); GPIO_TogglePin(GPIOA, GPIO_Pin_0); }} 【RISC-V MCU CH32V103测评】02:USART Demo 用户:740071911 注意,WCH-Link的串口只能发送,不能接收! 直接在上一个LED Demo基础上添加。 添加串口1,通过串口接收中断来接收数据,接收到回车键,一帧数据结束。主程序里处理串口数据(或丢弃或返回) 用其他usb转ttl工具,看看显示 串口调试助手显示结果 你认为这款开发板如何?之后嵌入式ARM还会继续登载国产替代者的更多测评信息。 附: 沁恒微电子MCU选型表 END 资料:21ic论坛,整理:付斌 ▍ 推荐阅读 国内MCU能替代国外产品吗?MCU的未来又将如何? STM32价格疯长下,盘点STM32的国产替代者 选微处理器MPU,还是单片机MCU?两者区别详解 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-01-14 关键词: 嵌入式 单片机

  • STM32价格疯长下,盘点STM32的国产替代者

    上周三(2020.10.28)的时候,我登陆立创商城,搜索stm32f103c8t6,单价15左右,100片的话,价格不到13。 今天(2020.11.5)再次登陆,搜索stm32f103c8t6,价格疯长到了20+ 疯了啊! 真的要考虑单片机型号的国产化了! 以下文章转自网络: 说起MCU,ST(意法半导体)的STM32单片机十几年来已经销售了几十亿颗,在国内几乎占有50%的市场,会使用STM32单片机也基本成为电子工程师的标配职业技能,然而2018年下半年的供货紧张,以及中兴事件,给我们硬件工程师敲了敲警钟,假如有一天我们必须替换下STM32单片机,国产芯有哪些是可以替代的呢? 北京兆易创新-GD32系列 GD32作为中国32位通用MCU领域的主流之选,以累计超过2亿颗的出货数量、超过1万的用户数量、20个系列300余款产品型号选择的广阔应用覆盖率稳居市场前列。GD32使用的是Cortex-M3内核,型号做到了与STM32相同型号的全兼容,方便替换,主频频率更高。 GD32F103是GD早期的产品,GD32E103和GD32F303是对GD32F103的升级和优化,所以4者是兼容的,虽然内核不同,但是通用外设几乎很少涉及到内核部分,在时间急迫的情况下可以使用ST的库开发。 一、相同点 1)外围引脚PIN TO PIN兼容,每个引脚上的复用功能也完全相同。2)芯片内部寄存器、外部IP寄存器地址和逻辑地址完全相同,但是有些寄存器默认值不同,有些外设模块的设计时序上和STM32有差异,这点差异主要体现在软件上修改,详情见下文。3)编译工具:完全相同例如:KEIL 、IAR4)型号命名方式完全相同,所以替代只需找尾缀相同的型号即可,例如:STM32F103C8T6 与 GD32E103C8T6。5)仿真工具:JLINK GDLINK 二、外围硬件区别 三、硬件替换需要注意的地方 从上面的介绍中,我们可以看出,GD32F30/E103系列和STM32F103系列是兼容的,但也需要一些注意的地方。 1)BOOT0必须接10K下拉或接GND,ST可悬空,这点很重要。2)RC复位电路必须要有,否则MCU可能不能正常工作,ST的有时候可以不要。3)有时候发现用仿真器连接不上。因为GD的swd接口驱动能力比ST弱,可以有如下几种方式解决:a、线尽可能短一些;b、降低SWD通讯速率;c、SWDIO接10k上拉,SWCLK接10k下拉。4)使用电池供电等,注意GD的工作电压,例如跌落到2.0V~2.6V区间,ST还能工作,GD可能无法启动或工作异常。 四、使用ST标准库开发需要修改的地方 1)GD对时序要求严格,配置外设需要先打开时钟,在进行外设配置,否则可能导致外设无法配置成功;ST的可以先配置在开时钟。 2)修改外部晶振起振超时时间,不用外部晶振可跳过这步。原因:GD与ST的启动时间存在差异,为了让GD MCU更准确复位。修改: 将宏定义:#define HSE_STARTUP_TIMEOUT ((uint16_t)0x0500)修改为:#define HSE_STARTUP_TIMEOUT ((uint16_t)0xFFFF) 3)GD32F10X flash取值零等待,而ST需要2个等待周期,因此,一些精确延时或者模拟IIC或SPI的代码可能需要修改。 原因:GD32采用专利技术提高了相同工作频率下的代码执行速度。修改:如果使用for或while循环做精确定时的,定时会由于代码执行速度加快而使循环的时间变短,因此需要仿真重新计算设计延时。使用Timer定时器无影响。 4)在代码中设置读保护,如果使用外部工具读保护比如JFLASH或脱机烧录器设置,可跳过此步骤。在写完KEY序列后,需要读该位确认key已生效,修改如下:总共需要修改如下四个函数: FLASH_Status FLASH_EraseOptionBytes(void);FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);uint32_t FLASH_GetWriteProtectionOptionByte(void);FlagStatus FLASH_GetReadOutProtectionStatus(void); 5)GD与ST在flash的Erase和Program时间上有差异,修改如下: 6)需求flash大于256K注意,小于256K可以忽略这项。 与ST不同,GD的flash存在分区的概念,前256K,CPU执行指令零等待,称code区,此范围外称为dataZ区。两者在擦写操作上没有区别,但在读操作时间上存在较大差别,code区代码取值零等待,data区执行代码有较大延迟,代码执行效率比code区慢一个数量级,因此data区通常不建议运行对实时性要求高的代码,为解决这个问题,可以使用分散加载的方法,比如把初始化代码,图片代码等放到data区。 总结:至此,经过以上修改,在不使用USB和网络能复杂协议的代码,就可以使用ST的代码操作了。 上海灵动微电子-MM32系列 MM32系列基于ARM Cortex-M0及Cortex-M3 内核,产品包括:针对通用高性能市场的MM32F系列,针对超低功耗及安全应用的MM32L系列,具有多种无线连接功能的MM32W系列,电机驱动及控制专用的MM32SPIN系列,以及OTP型的MM32P系列等,同样的管脚、型号等与ST全兼容,替换成本非常低。 华大半导体-HC32系列 有国企背景的HC32系列基于ARM Cortex-M0+及Cortex-M4内核,产品包括超低功耗应用的HC32L系列和针对电机应用市场的HC32M系列,针对通用市场的高性价比HC32F系列,与ST同型号产品管脚兼容,可以直接替换。 中科芯(CETC)                         中科芯的32位MCU产品可批量替换STM32的F103、F030、F031和F051等系列。基于ARM架构覆盖Cortex-M0、M3、M4内核八大系列产品,硬件引脚与STM32 P2P兼容,软件采用寄存器级兼容设计,对于已经使用ST系列MCU开发完成的程序,HEX文件可直接烧录到中科芯对应型号的MCU中即可运行,无需过多改动。 雅特力(Artery)             雅特力的AT32F403A/F407/ F413/ F415/F421系列,可批量替换STM32的F030、F303、F103、F107、F072、F401和F411等系列,其产品硬件引脚与STM32 P2P兼容,软件高度兼容,由于内核、SRAM、外设等性能相比STM32大幅度提升,AT32可一颗取代多颗STM32,另外还独有安全性&二次开发功能: security Lib,更宽的工作温度:-40~105度。 中微股份(CMSemicon)                                      中微股份的高性能低功耗高集成全领域的MCU,可批量替换STM32F030/031系列、STM32G030/031系列和STM32L031/051系列。 航顺(Hangshun)                       航顺已量产基于ARM Cortex-M0及Cortex-M3 内核的MCU产品包括:通用高性能市场的HK32F103家族,HK32F030/031/03X家族,存储器EEPROM家族。2019年即将推出的超低功耗7nA及安全应用的HK32L家族以及具有多种无线连接功能的HK32W/B家族,以满足客户多元化需求。 国产 芯任重道远 国产芯片在国内MCU市场的占有率在2%左右,市场非常低,还有很大的进步空间。以GD32为代表的国内芯片厂商的崛起势必冲击ST,但是我们也必须看到与ST之间的差距,产品线不完整,产品性能以及稳定性还不能完全与其匹敌,未来5年能抢下多少份额,我们拭目以待。 END 链接:https://blog.csdn.net/qq_23852045/article/details/109802955 链接:https://baijiahao.baidu.com/s?id=1632676931357810668&wfr=spider&for=pc 链接:https://mp.weixin.qq.com/s/xeFz-7mI_TUq3I8cjMtB2Q 版权归原作者所有,如有侵权,请联系删除。 ▍ 推荐阅读 成功为华为“续命:中国芯片之父张汝京 一个工程师的“噩梦”:刚分清CPU和GPU,却发现还有…… 这位“华为天才少年”,竟然要我用“充电宝”打《只狼》 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-01-13 关键词: 意法半导体 单片机

  • 单片机应用系统的可靠性设计

    要:可靠性设计是单片机应用系统设计必不可少的设计内容。 本文从现代电子系统的可靠性出发,详细论述了单片机应用系统的可靠性特点。提出了芯片选择、电源设计、PCB制作、噪声失敏控制、程序失控回复等集合硬件系统的可靠性设计技术和软件系统的可靠性设计技术的解决方法。可供单片机应用系统的开发人员借鉴与参考。 单片机应用系统的设计包括功能性设计、可靠性设计和产品化设计。其中,功能性是基础,可靠性是保障,产品化是前途。因此,从事单片机应用系统开发工作的设计人员必须掌握可靠性设计。 一、可靠性与可靠性设计 1.现代电子系统的可靠性 现代电子系统具有如下特点:嵌入式的计算机系统.智能化的体系结构;以计算机为核心的柔性硬件基础,由软件实现系统的功能;硬件系统有微电子技术的有力支持。单片机应用系统是当前最典型、最广泛的现代电子系统。 现代电子系统的可靠性表现为,在规定条件下,系统准确无误运行的能力.突出了可靠性的软件和运行中的失误概率。 可靠性设计则是在产品开发过程中,保证运行可靠的全部设计手段,甚至包括了产品出厂后软件升级中的可靠性设计。 由于软件的介入,可靠性问题除了二值可靠性的“失效”外.出现了除了“正常”与“失效”以外介于其间的诸如“出错”、“失误”、“不稳定”的多值可靠性问题。 2.单片机应用系统的可靠性特点 (1)系统运行状态的可靠性特点 单片机应用系统普遍采用CMOS器件,因此,经常的运行状态有静态运行与动态运行之分。 静态运行是指单片机在休闲或掉电方式下的工作状态。 此时,单片机指令停止运行。 外围电路被关断或电源被关断,系统中只有值守电路在工作。 因此,静态运行下 的系统不存在软件的可靠性问题,其可靠性主要表现在值守电路的抗干扰能力、系统中器件的静态参数余度,如直流特性参数余度、工作电压、工作稳定以及接插件的可靠性等。 动态运行是指单片机应用系统工作在程序运行状态。 此时的可靠性主要是软件运行的可靠性问题.表现在动态参数余度,如逻辑电平噪声容限、时钟误差、时序误差等。 (2)固化软件运行环境与可靠性 单片机应用系统中,CPU运行的是事先固化在单片机的程序存储器的软件.用户无法更改和输入新的程序。 这就避免r外来计算机病毒的侵袭,其可靠性表现在固化软件本身的可靠性和程序存储器数据保护的可靠性。 (3)时空边界性问题与可靠性 时空边界性问题普遍存在于单片机应用系统中.如单片机应用系统中采用二位十进制数代替四位公元纪年的定时时钟系统。 在跨越2000年时就会形成数据处理失误; 采用有限写入次数的程序存储器。 在超过写入次数的运行操作时会出现数据错误; 程序存储器保存数据也有一定的年限,超过此年限也会出现数据错误。 其它诸如计数容量.数据溢出,参数超边界应用都会带来可靠性问题。 因此.必须采取时空边界性问题的可靠性防范措施。 3.本质可靠性与可靠性控制 本质可靠性是只考虑系统功能要求的软、硬件可靠性设计,是可靠性设计的基础。 如采用CMOS电路代替7rrL电路提高噪声容限,增加系统抗干扰能力: 采用高可靠性的软硬件开发平台实现产品开发; 按照电磁兼容规范设计可靠的PCB等。 常用的可靠性控制设计有: 噪声失敏控制,时空边界管理,系统自检与自修复,出错后的安全性包容等。 二、硬件系统的可靠性设计 硬件系统的可靠性是系统本质可靠性和可靠性控制的基础。 1.硬件系统总体方案的可靠性设计 硬件系统总体方案的可靠性设计内容包括: (1)采用硬件平台的系统设计方法 单片机应用系统的硬件平台都是由相近似的应用系统基本电路组成,只适用于某一领域中的硬件系统设计。基于硬件平台设计的应用系统有基本的可靠性保证。一个良好的硬件平台应具备:标准化、系列化、规范化设计的电路系统;柔性特性的基本应用系统体系结构;丰富的软件支持;可靠性测试记录。 (2)最大的系统集成 最大的系统集成可以最大限度简化系统构成,有助于减少系统硬件失误概率。最大的系统集成应具备:依靠器件解决的思想;单片机选择实现系统的最大包容;0EM的支持。 2.器件选择的可靠性设计 单片机芯片的选择要满足系统集成的最大化要求;优选CMOS器件:为简化电路设计尽可能采用串行传输总线器件代替并行总线扩展的器件;选择保证可靠性的专用器件,如采用电源监控类器件、信号线路故障保护器、ESD(静电干扰)保护器、能实现电源短路保护的自聚合开关等。 三、软件系统的可靠性设计 在单片机应用系统可靠性设计中,软件设计最主要的任务是保证在过程空间中。应用程序按照给定的顺序有序运行。在高可靠性的硬件系统基础上。软件设计的可靠性保障了最少的软件错误以及在软件出错后仍能保证系统正常运行或安全运行。 1.本质可靠性的软件设计 软件的本质可靠性是指不依靠软件附加.最大限度减少自身错误及缺陷,并且要有足够的时序余度。 单片机系统在CPU的控制下实现分时操作.程序完全依靠时序调度、切换控制。程序运行的可控不仅要求时序准确,而且要有足够的时序余度。 第一,系统复位时序。多个器件复位的时序要求是主要问题。应保证MCU对外围可编程器件的初始化在该器件复位后进行。软件设计时,可以在系统上电复位后,MCU延迟片刻,确保外围器件复位后,再对其初始化。 第二,外围器件工作时序。对外围器件的工作时序必须分析清楚,MCU的操作必须保证时序信号的衔接控制和时序信号的时序余度。 第三,应用系统的状态转换时序。应用系统中的状态转换有MCU运行状态转换、外围器件运行状态转换和电源系统供电状态转换等。在程序设计中.必须考虑状态转换时过渡期对程序运行的影响,精心设计时序控制。通常。MCU本身的状态转换,都有自动监视、自动运行管理功能,程序设计只需按MCU数据手册及指令系统的操作要求进行即可。对于有较长过渡期的外围状态转换,可采取足够的延时或设置提前转换状态的办法。 第四,总线时序。单片机应用系统中有并行总线和串行总线,这些总线在规范化操作时,其时序数据通信协议保证。在虚拟总线方式时,虚拟总线运行的可靠性在于时序的准确模拟。并行总线要保证读、写操作指令运行下的读写时序:同步串行总线要保证时钟线控制下的同步时序;串行异步时序则要考虑波特率对数据传送的影响。 四、结束语 单片机应用系统的可靠性设计涉及硬件系统的抗干扰设计和软件系统的抗干扰设计,采取的措施多而复杂。实际应用时,应根据设计条件与目标要求,制定应用系统的可靠性等级,合理采用硬性可靠性措施。充分利用软件的可靠性设计,提高系统的抗干扰能力。 END 版权归原作者所有,如有侵权,请联系删除。 ▍ 推荐阅读 成功为华为“续命:中国芯片之父张汝京 一个工程师的“噩梦”:刚分清CPU和GPU,却发现还有…… 这位“华为天才少年”,竟然要我用“充电宝”打《只狼》 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-01-12 关键词: 可靠性设计 单片机

  • 单片机程序开发时,常见错误

    这里利用一个实际发生的例子,针对初级工程师经常犯的一个小错误,或者经常要走的一个弯路,做了针对性的纠正。希望可以帮到大家,文笔不好文章中有叙述不清的地方大家多多指教。 这篇文章我不是想说编程的规范性的东西,如果你想让自己的程序文件最起码直观的看起来美观、可读性强,推荐找华为的“C语言编程规范”。我只想说一说当我们的单片机遇到多个模块的数据需要处理,类似于“多任务”时我们应该怎么办? 背景是这样的,去年9月份开始安排一个工程师开始做电动汽车交流充电桩,机械设计部分由公司机械结构部门负责。充电桩的电子部分总体上分为X个部分(用到的资源),电阻触摸屏(RS232),M1卡读写(RS232),电能计量表(RS485),语音提示(SPI),电力开关(继电器IO),通讯接口(RS485、CAN)。 工程师做的过程非常勤奋,期间也是困难重重,改了很多个版本,总算今年6月把充电桩立起来了。 咱们来验收一下吧,结果发现读卡的时候不能处理触摸屏,播放语音的时候不能处理读卡,语音播放不能打断或者跳跃,反正就是所有事件必须一个一个按部就班的来,一旦操作错误就需要多次执行、等待、甚至重新来过。 一个工作3年多的工程师怎么会把产品做成这样呢?看看程序吧! 一看不要紧,吓一跳!整个的程序是没有逻辑的,一条线就往下写……   While(1)  {  //上电进入主程序 或 触发触摸屏  //播放提示语音  Delay();//等待播放完毕  //读取M1卡信息  Delay();//等待读卡数据返回  //播放提示语音  Delay();//等待播放完毕  //M1卡数据交互,判定下一步操作及提示  Delay();//等待数据处理完毕  ……  ……  } 这里说这个工程师基本上对于自己设计的产品没有任何的整体概念,或者说对自己开发的程序用到设计上会有怎样的实际效果根本就不清楚。 他犯了几个我们在程序开发过程中最忌讳的几个问题: 1、 delay(死等)这类函数只在应该实验室验证某个功能过程中用到,在实际的产品开发时无论是主循环while中,还是其调用的函数中,亦或是中断服务程序中绝对不可以用到。 2、 产品设计的各个子模块之间的逻辑关系太强,例如:必须等待播音完毕才能读卡进入下一步操作等。 我们讲,产品设计中只有各个事件处理模块间的逻辑关系弱化,才能更加灵活的进行处理。例如:两个事件A和B,如果程序开发时将A做成B事件的必要条件,B事件的触发就必须等待A事件的发生。反之如果A事件作为B事件处理的一个特殊情况,那么程序开发起来就变得灵活很多。   3、 没有考虑到单片机本身是一个单核单任务的架构,每一个事件都会独占CPU内核,当多个任务模块同时存在时我们应该对各个事件进行区分,我们应当分情况、分事件实时性要求等区分对待。   那么针对于这样的问题,或者是遇到类似的项目我们应该如何处理呢?   我提几条建议:   1、将硬件系统区分为独立单元单独做成底层驱动函数和应用函数,并且函数正常应该有参数和返回值,其中返回值是必要的。如何衡量这类函数呢?这类函数可移植性强,只要一个.h文件和一个.c文件就可以随意放到任何工程中。例如:语音播放、M1读卡、485处理等等。   2、将1中的所有函数进行时间评估,评估点有两个。一个是函数的执行时间t,第二个是函数的周期性发生的时间T,一个最基本的条件是t < T,理想情况应该是t

    时间:2021-01-08 关键词: C语言 单片机

  • Microchip推出全新电源控制参考设计,实现次级侧单片机控制主电源

    Microchip推出全新电源控制参考设计,实现次级侧单片机控制主电源

    在现代离线AC-DC电源解决方案中,可编程性和自适应控制提供了智能家居设备所需的灵活性和智能性,以便更好地与电源系统连接。在这些系统中,次级侧单片机(MCU)通常无法在不使用独立偏置电源的情况下启动系统。Microchip Technology Inc.(美国微芯科技公司)推出一款全新参考设计,利用MCP1012高压辅助AC-DC控制器解决了这一问题,可在许多应用中取消独立偏置电源。MCP1012离线辅助器件使系统能将功率和占空比的控制转移到次级侧单片机上。通过简化设计、减小尺寸和成本,系统与负载之间的控制可以实现更加精确和有目的地耦合。   参考设计采用专利隔离技术用于隔离反馈。这项专利隔离技术称为Inde-Flux变压器技术,已向Würth Elektronik eiSos公司授权。Inde-Flux变压器(部件编号750318659)是Würth Elektronik eiSos利用该专利制造的第一款变压器,将作为Microchip 15W MCP1012离线参考设计的组件出售。这款变压器将信号功率和信号通信结合到一个器件中,无需光反馈或独立的信号变压器。全新参考设计还可以选择采用更传统的方法,使用平面脉冲变压器,与更传统的光耦合器和信号变压器一起工作。通过使用该变压器和Microchip新推出的MCP1012 AC-DC控制器以及SAM D20系列32位单片机组合,可实现次级侧控制。 MPC1012初级侧辅助控制器为次级侧单片机提供了系统启动、门控和保护离线反激转换器的功能。该器件具有一系列功能,如直接测量和主动稳压或稳流,通过直接闭环实现高环路带宽,以及简化负载参考系统的通信。 15W MCP102离线参考设计为15W离线电源设计提供了主要工作元素,并配备了必要固件,以消除初级侧辅助电源。这可以降低系统的复杂性,包括消除许多应用中对光耦的需求,如家电和智能音箱。在Würth Elektronik eiSos的支持下,Inde-Flux变压器技术可根据需要扩展到不同电压和功率水平的标准和定制变压器设计。 Microchip模拟、电源和接口业务部高级副总裁Rich Simoncic表示:“将采用Inde-Flux技术的Würth Elektronik eiSos变压器与我们的MCP1012 AC-DC控制器和SAM D20系列32位单片机相结合,为离线电源管理创造了一个独特的解决方案。这些器件能够更简单、更可靠地实现主元件和辅助元件之间的复杂双向通信,这些元件用于许多利用离线电源的隔离应用中。当解决方案用于具有次级侧单片机的系统时,客户可节省高达60%的偏置电源面积,并将偏置电源物料清单成本降低3美元以上。” 开发工具 15W MCP1012 离线参考设计包括用户指南,并附带原理图和物料清单、设计文件、固件和一个演示装置。Microchip还为MCP1012 AC-DC控制器提供了基础款1W评估板DT100118。 供货与定价 15W MCP1012离线参考设计,部件编号为EV37F82A,现已上市,每件售价225美元。DT100118 1W参考设计现已上市,每件售价115美元。MCP1012-V/EKA现已上市,5000件起售的单价是0.40美元起。 如需了解更多信息,请联系Microchip销售代表、全球授权分销商或访问Microchip网站。

    时间:2021-01-07 关键词: Microchip 电源控制 单片机

  • 实用:牛人总结的单片机三种应用程序架构!

    在工作中经过摸索实验,总结出单片机大致应用程序的架构有三种: 1. 简单的前后台顺序执行程序,这类写法是大多数人使用的方法,不需用思考程序的具体架构,直接通过执行顺序编写应用程序即可。 2. 时间片轮询法,此方法是介于顺序执行与操作系统之间的一种方法。 3. 操作系统,此法应该是应用程序编写的最高境界。 下面就分别谈谈这三种方法的利弊和适应范围等。 一、顺序执行法 这种方法,这应用程序比较简单,实时性,并行性要求不太高的情况下是不错的方法,程序设计简单,思路比较清晰。但是当应用程序比较复杂的时候,如果没有一个完整的流程图,恐怕别人很难看懂程序的运行状态,而且随着程序功能的增加,编写应用程序的工程师的大脑也开始混乱。即不利于升级维护,也不利于代码优化。本人写个几个比较复杂一点的应用程序,刚开始就是使用此法,最终虽然能够实现功能,但是自己的思维一直处于混乱状态。导致程序一直不能让自己满意。 这种方法大多数人都会采用,而且我们接受的教育也基本都是使用此法。对于我们这些基本没有学习过数据结构,程序架构的单片机工程师来说,无疑很难在应用程序的设计上有一个很大的提高,也导致了不同工程师编写的应用程序很难相互利于和学习。 本人建议,如果喜欢使用此法的网友,如果编写比较复杂的应用程序,一定要先理清头脑,设计好完整的流程图再编写程序,否则后果很严重。当然应该程序本身很简单,此法还是一个非常必须的选择。 下面就写一个顺序执行的程序模型,方便和下面两种方法对比: 代 码 /************************************************************************************** * FunctionName   : main() * Description    : 主函数 * EntryParameter : None * ReturnValue    : None **************************************************************************************/ int main(void) { uint8 keyValue; InitSys();                  // 初始化 while (1) { TaskDisplayClock(); keyValue = TaskKeySan(); switch (keyValue) { case x: TaskDispStatus(); break; ... default: break; } } } 二、时间片轮询法 时间片轮询法,在很多书籍中有提到,而且有很多时候都是与操作系统一起出现,也就是说很多时候是操作系统中使用了这一方法。不过我们这里要说的这个时间片轮询法并不是挂在操作系统下,而是在前后台程序中使用此法。也是本贴要详细说明和介绍的方法。 对于时间片轮询法,虽然有不少书籍都有介绍,但大多说得并不系统,只是提提概念而已。下面本人将详细介绍这种模式,并参考别人的代码建立的一个时间片轮询架构程序的方法,我想将给初学者有一定的借鉴性。 在这里我们先介绍一下定时器的复用功能。 使用1个定时器,可以是任意的定时器,这里不做特殊说明,下面假设有3个任务,那么我们应该做如下工作: 1. 初始化定时器,这里假设定时器的定时中断为1ms(当然你可以改成10ms,这个和操作系统一样,中断过于频繁效率就低,中断太长,实时性差)。 2. 定义一个数值: 代 码 #define TASK_NUM   (3)                  //  这里定义的任务数为3,表示有三个任务会使用此定时器定时。 uint16 TaskCount[TASK_NUM] ;           //  这里为三个任务定义三个变量来存放定时值 uint8  TaskMark[TASK_NUM];             //  同样对应三个标志位,为0表示时间没到,为1表示定时时间到。 3. 在定时器中断服务函数中添加: 代 码 /************************************************************************************** * FunctionName : TimerInterrupt() * Description : 定时中断服务函数 * EntryParameter : None * ReturnValue : None **************************************************************************************/ void TimerInterrupt(void) { uint8 i; for (i=0; i unsigned char kbscan(void) { unsigned char sccode,recode; P2=0xf8; if ((P2&0xf8)!=0xf8) { delay(100); //延时20ms去抖--------这里太费时了,很糟糕 if((P2&0xf8)!=0xf8) { sccode=0xfe; while((sccode&0x08)!=0) { P2=sccode; if ((P2&0xf8)!=0xf8) break; sccode=(sccode<<1)|0x01; } recode=(P2&0xf8)|0x0f; return(sccode&recode); } } return (KEY_NONE); } While( kbscan() != KEY_NONE); //死循环等待 While(kbsan() != KEY_NONE ) { Delay(10); If(Num++ > 10) Break; } void ClearKeyFlag(void) { KeyDebounceFlg = 0; KeyReleaseFlg = 0; } void ScanKey(void) { ++KeyDebounceCnt;//去抖计时(这个计时也可以放在后台定时器计时函数中处理) KeyCode = kbscan(); if (KeyCode != KEY_NONE) { if (KeyDebounceFlg)//进入去抖状态的标志位 { if (KeyDebounceCnt > DEBOUNCE_TIME)//大于了去抖规定的时间 { if (KeyCode == KeyOldCode)//按键依然存在,则返回键值 { KeyDebounceFlg = 0; KeyReleaseFlg = 1;//释放标志 return; //Here exit with keycode } ClearKeyFlag(); //KeyCode != KeyOldCode,只是抖动而已 } }else{ if (KeyReleaseFlg == 0) { KeyOldCode = KeyCode; KeyDebounceFlg = 1; KeyDebounceCnt = 0; }else{ if (KeyCode != KeyOldCode) ClearKeyFlag(); } } }else{ ClearKeyFlag();//没有按键则清零标志 } KeyCode = KEY_NONE; } // avr 单片机 中4*3扫描状态机实现 char read_keyboard_FUN2() { static char key_state = 0, key_value, key_line,key_time; char key_return = No_key,i; switch (key_state) { case 0: //最初的状态,进行3*4的键盘扫描 key_line = 0b00001000; for (i=1; i<=4; i++) // 扫描键盘 { PORTD = ~key_line; // 输出行线电平 PORTD = ~key_line; // 必须送2次!!!(注1) key_value = Key_mask & PIND; // 读列电平 if (key_value == Key_mask) key_line <<= 1; // 没有按键,继续扫描 else { key_state++; // 有按键,停止扫描 break; // 转消抖确认状态 } } break; case 1: //此状态来判断按键是不是抖动引起的 if (key_value == (Key_mask & PIND)) // 再次读列电平, { key_state++; // 转入等待按键释放状态 key_time=0; } else key_state--; // 两次列电平不同返回状态0,(消抖处理) break; case 2: // 等待按键释放状态 PORTD = 0b00000111; // 行线全部输出低电平 PORTD = 0b00000111; // 重复送一次 if ( (Key_mask & PIND) == Key_mask) { key_state=0; // 列线全部为高电平返回状态0 key_return= (key_line | key_value);//获得了键值 } else if(++key_time>=100)//如果长时间没有释放 { key_time=0; key_state=3;//进入连键状态 key_return= (key_line | key_value); } break; case 3://对于连键,每隔50ms就得到一次键值,windows xp 系统就是这样做的 PORTD = 0b00000111; // 行线全部输出低电平 PORTD = 0b00000111; // 重复送一次 if ( (Key_mask & PIND) == Key_mask) key_state=0; // 列线全部为高电平返回状态0 else if(++key_time>=5) //每隔50MS为一次连击的按键 { key_time=0; key_return= (key_line | key_value); } break; } return key_return; } // Timer 0 比较匹配中断服务,4ms定时 interrupt [TIM0_COMP] void timer0_comp_isr(void) { display(); // 调用LED扫描显示 …………………… } void display(void) // 8位LED数码管动态扫描函数 { PORTC = 0xff; // 这里把段选都关闭是很必要的,否则数码管会产生拖影 PORTA = led_7[dis_buff[posit]]; PORTC = position[posit]; if (++posit >=8 ) posit = 0; } 以上的代码ChkRxFrame()可以放于串口接收数据处理函数RxProcess() 中,然后放入主循环中执行即可。以上用一个计时变量RxTimer,很微妙的解决了接收帧超时的放弃帧处理,它没有用任何等待,而且主循环中每次只是接收一个字节数据,时间很短。 我们开始架构整个系统的框架: 我们选用一个系统不常用的TIMER来产生系统所需的系统基准节拍,这里我们选用4ms; 在meg8中我们代码如下: 然后我们设计一个TimeEvent()函数,来调用一些在以指定的频率需要循环调用的函数, 比如每个4ms我们就进行喂狗以及数码管动态扫描显示,每隔1s我们就调用led闪烁程序,每隔20ms我们进行键盘扫描程序; 显然整个思路已经很清晰了,cpu需要处理的循环事件都可以根据其对于时间的要求很方便的加入该函数中。但是我们对这事件有要求: 执行速度快,简短,不能有太长的延时等待,其所有事件一次执行时间和必须小于系统的基准时间片4ms(根据需要可以加大系统基准节拍)。 所以我们的键盘扫描程序,数码管显示程序,串口接收程序都如我先前所示。如果逼不得已需要用到较长的延时(如模拟IIc时序中用到的延时) 我们设计了这样的延时函数: void RunTime250Hz (INT8U delay)//此延时函数的单位为4ms(系统基准节拍) 我们需要延时的时间=delay*系统记住节拍4ms,此函数就确保了在延时的同时,我们其它事件(键盘扫描,led显示等)也并没有被耽误; 好了这样我们的主函数main()将很简短: 整体看来我们的系统就成了将近一个万能的模版了,根据自己所选的cpu,选个定时器,在添加自己的事件函数即可,非常灵活方便实用,一般的单片机能胜任的场合,该模版都能搞定。 整个系统以全局标志作为主线,形散神不散;系统耗费比较小,只是牺牲了一个Timer而已,在资源缺乏的单片机中,非常适合;曾经看过一个网友的模版“单片机实用系统”,其以51为例子写的,整体思路和这个差不多,不过他写得更为规范紧凑,非常欣赏;但个人觉得代码开销量要大些,用惯了都一样哦。但是由于本系统以全局标志为驱动事件,所以比较感觉比较凌乱,全局最好都做好注释,而其要注意一些隐形的函数递归情况,千万不要递归的太深哦(有的单片机不支持)。 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-01-06 关键词: 架构 应用程序 单片机

  • 老司机带你入门新塘N76E003单片机

    出品 21ic中国电子网 一路向北lm 网站:bbs.21ic.com 第一个问题,究竟要玩哪一个芯? 今年真是变幻莫测的一年,芯片的真是流水账的价格,一天一个样,翻翻自己的抽屉,一堆的板卡,不知玩弄哪一个,一直想玩弄一下新塘的片子,可惜论坛没怎么做过新塘的开发板评测活动(也有可能做过,可能我只是一个新人),看到很多项目都用N76E003这个片子,今天就来研究一下,给大家一个提示哈,别指望我写太深的东西! 先来介绍一下新塘官方的样板:NuTiny-SDK-N76E003,究竟长什么样子,看下面的图就知道了,有一种一份为二的冲动,的确有时候也可以这么玩,设计的初衷就是让你掰着玩的。         板卡长这样(虽然我没有) 这块板卡我虽然没有具体用过,也没有拿到新塘官方的样板,但是这颗TargetChip N76E003的确挺火的,板卡分为左右两半部分,左边是以TargetChip的核心板,引出了相关的引脚,一个复位按钮,一个电源指示灯,一个用户IOLED,同时也引出了VCC和GND电源引脚。右边是新塘设计的Nu-Link-Me,主要实现对新塘系列的单片机的下载和调试功能,Nu-Link-Me的主控使用的是:MCU12SRE3DE,这颗芯片暂时没有详细查资料,后面给大家补上,网上很多大神将Nu-Link-Me魔改为DAP,Nu-Link-Me就跟我们熟悉的ST-LinkULink类似,使用USB一键下载和调试目标芯片程序,新塘这里称Nu-Link-Me的主控为ICEController,此外,Nu-Link-Me还支持虚拟串口,使用SW3拨码开关来使能和失能虚拟串口,使能虚拟串口时,N76E003AT20的UART0作为串口和PC串口助手通讯。   第二个问题,这颗芯开发环境如何搭建? 张三说IAR好用,李四说Keil 好用 pack包多,王五说我就喜欢捣鼓,用VScode有些芯片也可以用…………..,开发IDE云里雾里,最好上手还是keil C51,那么如何在keil C51上使用Nu-Link-Me来下载和调试程序? 主要分为以下几步: 第一步:修改Debug 使用 Nuvoton 8051 Keil C51 Driver 作为调试器 第二步:确保设置界面按照以下连接方式进行默认设置。 第三步:Flash编程工具记得使用Nuvoton 8051 Keil C51 Driver 哦! 这样就可以使用Nu-Link-Me一键下载和调试程序了。           差补知识点1:Nu-Link-Me 原理图分析: 下图是从新塘官网down下来的Nu-Link-Me 原理图,是不是跟ST-Link有些面熟?本人使用过赛元的MCU,赛元的调试器使用的是STM32作为主控,有兴趣的可以去研究一下,同样是调试器,Nu-Link-Me也大同小异,只要拿到固件,参考其原理图设计,自己就可以做出一个Nu-Link-Me。  Nu-Link-Me原理图 先来看一下Debug接口,Nu-Link-Me使用的是SWD五线接口,主要包括:VCC、GND、ICE_DAT(数据)、ICE_CLK(时钟)、ICE_RST(复位),有些SWD接口可以不用接RST,只需要VCC、GND、ICE_DAT(数据)、ICE_CLK(时钟)、四线即可。Debug SWD端口只要实现对Nu-Link-Me的固件更新。 Nu-Link-Me 主控MCU12SRE3DE使用PC10 ICEDAT(数据)、PC9 ICECLK(时钟)、PC8ICERST(复位),作为NuTiny-SDK-N76E003 板卡N76E003芯片的调试与下载口,ICEDAT->TICEDAT、 ICECLK-> TICECLK、ICERST-> TICERST,此外还通过JP2端口引出。       再来看一下USB接口,Nu-Link-Me使用的是mini USB接口,DM、DP接入33R的电阻到USB的数据口,最终连接到MCU12SRE3DE的USB_D- (D-) 和USB_D+ (D+)引脚。 Nu-Link-Me主控MCU12SRE3DE串口0默认通过ICE_TX -> Tiny_Tx, ICE_RX -> Tiny_Rx接到目标芯片N76E003的串口,通过SWD3是使能是否打开和关闭虚拟串口。       Nu-Link-Me主控时钟选择12M无缘晶振,外加20pf电容辅助起振,复位电路使用10uf的有极性电容和10K电阻硬件复位。        Nu-Link-Me有四个状态指示灯,分别是:ICE红  ISP黄  IDLE红 BUSY 绿,通过330R的排阻接到VCC, 四个状态指示灯分别表示 Nu-Link-Me所处于的状态,用户可以根据四个状态指示判断Nu-Link-Me正常与否。 Nu-Link-Me 电源使用USBVBUS 5V供电,再使用AMS1117_3.3V,稳压到3.3V为主控供电,这也是绝大多数开发板使用的电源电路方案。   差补知识点2:NuTiny-SDK-N76E003 原理图分析: NuTiny-SDK-N76E003板卡的左半部分就有一颗孤零零的N76E003,其20pin引脚,却可以有18 个IO的能力,强大到爆炸。这边的板卡主要是将其IO引出,预留下载调试口连接Nu-Link-Me和串口等。此外还有复位电路和LED指示电路蛮简单的设计。 N76E003芯片,无需外接时钟晶振,只需要复位电路即可构成最小系统,复位电路同样使用10K的电阻和10uf的电容,按钮按下实现N76E003芯片硬件复位。 NuTiny-SDK-N76E003中有两颗LED,电源LED和GPIO LED,调试代码时可以点亮GPIO LED来指示程序的运行状态。   第三个问题,这颗芯有多少内功? 内功1: N76E003,是新唐高速1T  8051 单片机系列产品, 18 KB Flash ROM、可配置DataFlash与高容量1 KB SRAM ,支持2.4V 至 5.5V 宽工作电压与 - 40 ℃ 至105 ℃ 工作温度,并具备高抗干扰能力 7 kVESD/4 kV EFT。 内功2: N76E003 在20 pin封装下提供高达18根I/O脚位;周边包含双串口、 SPI 、 I²C 、6通道 PWM 输出。 放大招: 内建优于同类产品之 < 2% 误差之高精确度16 MHzRC晶振,高分辨率8通道12位 ADC ;并具备自我唤醒、欠压检测等功能;提供TSSOP20( 4mm*6.5mm ) 与QFN20 ( 3mm*3mm ) 小封装,兼具高性能与设计弹性。 无所不能: 门禁系统/警报器、温度传感设备、蓝牙音箱、电动车表头、数字电压表头、气体检测器、采集器、充电器、美容仪器、小家电等。 补一个表给大家看,刷新一下三观:   第四个问题,这颗芯该怎么玩? N76E003原理图参考了NuTiny-SDK-N76E003,我这里新加了一个USB串口功能,使用的CH340N,8p 简单方便。 PCB部分很简单,双层板,还添加了小小的丝印,板子过几天送去打印,后续可以考虑画一块拓展板卡,会出一些N76E003基于本版卡的测试工程发布到论坛,方便大家的学习和调试使用。这里的GND没连接,喜欢直接使用GND来铺铜 参考新塘给的N76E003 Demo是上手最快的方法,官方写出来的参考历程是最具有权威的,后期为了项目的需求,可以将写的代码托管到git平台上,组建团队一起来开发和学习。涉及到具体的编程我就不多说了,毕竟那是你们的战场,我很想写点代码给你们展示,可是我也没有现成的板卡啊,还是要板卡打印出来以后,硬件调试没有问题,我会在论坛发布一些基于本板卡的测试工程。本次基于新塘N76E003 上手教程就到这里,欢迎继续关注后期精彩板卡例程篇,这里给自己挖坑! 出品:一路向北lm 免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!

    时间:2021-01-04 关键词: 新塘 单片机

首页  上一页  1 2 3 4 5 6 7 8 9 10 下一页 尾页
发布文章

技术子站

更多

项目外包