单片机

PIC32CXMT包含单核、双核和系统级芯片(SOC)等三层器件,以提供最大的灵活性,简化智能仪表和通信基础设施的开发

随着不同的通信解决方案被集成到设计框架中,以及监管合规性要求的规定,智能仪表的设计复杂性也在不断增加。为了满足对开发功能丰富且简单的智能仪表设计方案的日益增长的需求,Microchip Technology Inc.(美国微芯科技公司)今日宣布推出配备全新MPL460电力线通信(PLC)调制解调器的PIC32CXMT系列32位单片机。这款新的单片机(MCU)器件是下一代智能仪表平台,适用于工业物联网、商业和工业仪表应用。该平台拥有最高可达200 MHz的运行性能和高达560 KB存储空间(SRAM)的广泛可扩展性。

2A8DpQTQjr.jpg

为了给开发人员提供扩展产品的最佳灵活性,PIC32CXMT系列包含基于Arm® Cortex®-M4F单个内核、Arm Cortex-M4双内核和系统级芯片(SoC)器件的三种型号。MPL460 PLC调制解调器集成了用于信号放大的线路驱动器,由于采用了D类拓扑结构,因而减少了物料清单,并保持了超过40%的顶级性能的信号注入效率。PLC调制解调器有助于提高效率和可靠性,基于输送到负载的功率和从电源中获取的功率,在传输过程中全面减少来自源头的消耗。

Microchip智慧能源业务部总监Kourosh Boutorabi表示:“新型PIC32CXMT单片机与MPL460 PLC调制解调器搭配使用,可提供无与伦比的可扩展性和性能,支持各种仪表架构。我们非常成功的第二代仪表产品表明,我们致力于提供丰富的系统级芯片(SoC)组合,以实现灵活安全的智能仪表平台,支持一流的计量设计以及领先的连接性。”

该平台提供多种收发器解决方案,包括无线电/PHYPLC/PHY以及PLC+RF混合解决方案。还有一个选项是计量和通信软件套件,符合美国国家标准协会(ANSI)和国际电工委员会(IEC)计量标准,精度可达 0.2% 级。它还支持G3-PLCPRIME等有线和无线通信标准。

随着智能仪表设备联网,安全性需求在任何设计中都至关重要。PIC32CXMT单片机提供标准和专有的片上硬件安全特性,以确保最佳性能和存储利用率。

开发工具

PIC32CXMT系列和MPL460调制解调器MicrochipMPLAB® Harmony v3嵌入式软件框架支持。其他资源包括IAR系统、ArmKeil开发环境、G3-PLCPRIME软件。

供货与定价

PIC32CXMT系列和MPL460目前提供数量有限的样品。如需了解更多信息,请联系Microchip销售代表。

  • 单核:SAM4CPIC32CXMT-G系列

  • 双核:PIC32CXMT-C系列

  • 系统级芯片:SAM4CMPIC32CXMT-SH系列

资源

可通过Flickr或联系编辑获取高分辨率图片(可免费发布):

Microchip Technology Inc. 简介

Microchip Technology Inc.是致力于智能、互联和安全的嵌入式控制解决方案的领先供应商。其易于使用的开发工具和丰富的产品组合让客户能够创建最佳设计,从而在降低风险的同时减少系统总成本,缩短上市时间。Microchip的解决方案为工业、汽车、消费、航天和国防、通信以及计算市场中12万多家客户提供服务。Microchip总部位于美国亚利桑那州Chandler市,提供出色的技术支持、可靠的产品交付和卓越的质量。详情请访问公司网站www.microchip.com

围观 12

单片机软件延时时间控制

cathy的头像

一、简述

记--通过代码方式实现软件延时(不精确延时)。

二、指令周期

单片机需要一个时钟信号送给内部各个电路,才能使它们有节拍地协同工作。时钟信号的频率是由外部震荡电路的晶振频率决定的。

外接晶振的频率 = 时钟信号的频率 = 工作频率。(如24MHz,12MHz,11.0592MHz)

震荡周期:为单片机提供时钟脉冲的振荡源的周期。

震荡周期 = 1/晶振频率          (如晶振频率是12MHz时,振荡周期 = 1/12MHz = (1/12)us)

机器周期:51系列单片机的一个机器周期由12个震荡周期组成。

机器周期 = 12 * 振荡周期      

(如晶振频率是24MHz时,振荡周期 = 1/24MHz = (1/24)us,机器周期 = 12*(1/24)us = 0.5us)

(如晶振频率是12MHz时,振荡周期 = 1/12MHz = (1/12)us,机器周期 = 12*(1/12)us = 1us)

单片机的内存分配(变量的存储位置)详解

cathy的头像

对于初学者而言,对单片机的内存分配往往最让人头疼,很多人学了单片机几年 都不知道单片机内部的内存使用情况是如何分配的。要了解 ROM(flash)、RAM(sram)启动,首先 需要对 链接器 Linker 如何分配内存有一定的了解。

嵌入式开发中,UART串口是最常见的一种通信接口,你知道为啥串口这么常见吗?本文就带你深入了解串口最底层的本质内容。

一、什么是串口通讯?

串行通讯是指仅用一根接收线和一根发送线就能将数据以位进行传输的一种通讯方式。尽管串行通讯的比按字节传输的并行通信慢,但是串口可以在仅仅使用两根线的情况下就能实现数据的传输。

典型的串口通信使用3根线完成,分别是地线、发送、接收。由于串口通信是异步的,所以端口能够在一根线上发送数据同时在另一根线上接收数据。串口通信最重要的参数是波特率、数据位、停止位和奇偶的校验。对于两个需要进行串口通信的端口,这些参数必须匹配,这也是能够实现串口通讯的前提。

“图1:串行通讯示数据传输意图"
图1:串行通讯示数据传输意图

二、串口通讯的通讯协议?

最初数据是模拟信号输出简单过程量,后来仪表接口出现了RS232接口,这种接口可以实现点对点的通信方式,但这种方式不能实现联网功能,这就促生了RS485。

我们知道串口通信的数据传输都是0和1,在单总线、I2C、UART中都是通过一根线的高低电平来判断逻辑1或者逻辑0,但这种信号线的GND再与其他设备形成共地模式的通信,这种共地模式传输容易产生干扰,并且抗干扰性能也比较弱。所以差分通信、支持多机通信、抗干扰强的RS485就被广泛的使用了。

RS485通信最大特点就是传输速度可以达到10Mb/s以上,传输距离可以达到3000米左右。大家需要注意的是虽然485最大速度和最大传输距离都很大,但是传输的速度是会随距离的增加而变慢的,所以两者是不可以兼得的。

三、串口通讯的物理层

串口通讯的物理层有很多标准,例如上面提到的,我们主要讲解RS-232标准,RS-232标准主要规定了信号的用途、通讯接口以及信号的电平标准。

“精华

在上面的通讯方式中,两个通讯设备的"DB9接口"之间通过串口信号线建立起连接,串口信号线中使用"RS-232标准"传输数据信号。由于RS-232电平标准的信号不能直接被控制器直接识别,所以这些信号会经过一个"电平转换芯片"转换成控制器能识别的"TTL校准"的电平信号,才能实现通讯。

下图为DB9标准串口通讯接口:

“精华

DB9引脚说明:

“精华

上表中的是计算机端的DB9公头标准接法,由于两个通讯设备之间的收发信号(RXD与TXD)应交叉相连,所以调制调解器端的DB9母头的收发信号接法一般与公头的相反,两个设备之间连接时,只要使用"直通型"的串口线连接起来即可。

“精华

串口线中的RTS、CTS、DSR、DTR及DCD信号,使用逻辑 1表示信号有效,逻辑0表示信号无效。例如,当计算机端控制DTR信号线表示为逻辑1时,它是为了告知远端的调制调解器,本机已准备好接收数据,0则表示还没准备就绪。

四、波特率

波特率是指数据信号对载波的调制速率,它用单位时间内载波调制状态改变的次数来表示;

“精华

比如波特率为9600bps;代表的就是每秒中传输9600bit,也就是相当于每一秒中划分成了9600等份。

因此,那么每1bit的时间就是1/9600秒=104.1666...us。约0.1ms。既然是9600等份,即每1bit紧接着下一个比特,不存在额外的间隔。两台设备要想实现串口通讯,这收发端设置的波特率必须相同,否则是没办法实现通讯的。

收发波特率一致可以实现通讯:

“精华

收发波特率不一致,导致RX端不能正常接收:

“精华

五、串口通讯的数据结构

“精华

起始位: 起始位必须是持续一个比特时间的逻辑0电平,标志传输一个字符的开始,接收方可用起始位使自己的接收时钟与发送方的数据同步。

数据位: 数据位紧跟在起始位之后,是通信中的真正有效信息。数据位的位数可以由通信双方共同约定。传输数据时先传送字符的低位,后传送字符的高位。

奇偶校验位: 奇偶校验位仅占一位,用于进行奇校验或偶校验,奇偶检验位不是必须有的。如果是奇校验,需要保证传输的数据总共有奇数个逻辑高位;如果是偶校验,需要保证传输的数据总共有偶数个逻辑高位。

停止位: 停止位可以是是1位、1.5位或2位,可以由软件设定。它一定是逻辑1电平,标志着传输一个字符的结束。

空闲位: 空闲位是指从一个字符的停止位结束到下一个字符的起始位开始,表示线路处于空闲状态,必须由高电平来填充。

六、单双工通讯

单工: 数据传输只支持数据在一个方向上传输;

半双工: 允许数据在两个方向上传输,但某一时刻只允许数据在一个方向上传输,实际上是一种切换方向的单工通信,不需要独立的接收端和发送端,两者可合并为一个端口;

全双工: 允许数据同时在两个方向上传输,因此全双工通信是两个单工方式的结合,需要独立的接收端和发送端。

“精华

七、STM32中的串口通讯

STM32串口通信接口有两种,分别是:UART(通用异步收发器)、USART(通用同步异步收发器),对于大容量STM32F10x系列芯片,分别由3个USART和两个UART。

“精华

对于两芯片的间的连接,两个芯片GND共地,同时TXD和RXD交叉连接,这样两个芯片间可进行TTL电平通信。

但如果对于芯片和PC机相连,除了共地条件外,不能使用如上的直接交叉连接,虽然两者都有TXD和RXD引脚,但通常PC机使用的是RS232接口(9针),通常是TXC和RXD经过电平转换得到,故如果要使芯片与PC机的RS232接口直接通信,需要将芯片的输入输出端口也电平转换为RS232类型,再交叉连接,二者的电平标准不同:

单片机的点评标准(TTL电平):+5V表示1,0V表示0;RS232电平标准:+15/+13V表示0,-15/-13表示1。

“精华

因此单片机与PC机进行串口通信应该遵循:在单片机串口与上位机给出的RS232口之间,通过电平转换电路实现TTL电平与RS232电平间的转换。如果使用USB转串口也可以实现串口通讯,USB转串口电路图如下所示。

“精华

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

围观 41

单片机如果缺少调试功能,就好比失去了灵魂。

如今众多Cortex-M处理器能这么方便调试,在于有一项基于Arm Cortex-M处理器设备的CoreSight技术,该技术引入了强大的新调试(Debug)和跟踪(Trace)功能。

下面就来重点讲讲关于CoreSight中调试和跟踪的相关内容。

调试和跟踪功能

CoreSight两个主要功能就是调试和跟踪功能。

1.调试功能

  • 运行处理器的控制,允许启动和停止程序
  • 单步调试源码和汇编代码
  • 在处理器运行时设置断点
  • 即时读取/写入存储器内容和外设寄存器
  • 编程内部和外部FLASH存储器

2.跟踪功能

  • 串行线查看器(SWV)提供程序计数器(PC)采样,数据跟踪,事件跟踪和仪器跟踪信息
  • 指令(ETM)跟踪直接流式传输到您的PC,从而实现历史序列的调试,软件性能分析和代码覆盖率分析

一张图了解整体内容:

“单片机调试时的那些技术"

JTAG

JTAG是行业标准的接口,用于下载和调试目标处理器上的程序以及许多其他功能。它提供了连接设备的简便方法,并且在所有基于Arm处理器的设备上都可用。JTAG接口可与基于Cortex-M的设备一起使用,以访问CoreSight调试功能。

1.JTAG历史

JTAG是联合测试工作组(Joint Test Action Group)的简称,是在名为标准测试访问端口和边界扫描结构的IEEE的标准1149.1的常用名称。此标准用于验证设计与测试生产出的印刷电路板功能。

1990年JTAG正式由IEEE的1149.1-1990号文档标准化,在1994年,加入了补充文档对边界扫描描述语言(BSDL)进行了说明。从那时开始,这个标准被全球的电子企业广泛采用,边界扫描几乎成为了JTAG的同义词。---引用维基百科

2.JTAG接口

JTAG的接口通常是4/5个接脚接口连到芯片上:

  • TDI(测试数据输入)
  • TDO(测试数据输出)
  • TCK(测试时钟)
  • TMS(测试模式选择)
  • TRST(测试复位)可选

“单片机调试时的那些技术"

SWD串行线调试

SWD,Serial Wire Debug(串行线调试)模式是标准JTAG接口的替代方法,它仅使用两个引脚即可提供与JTAG相同的调试功能,而不会降低性能,并通过串行线查看器(SWV)引入了数据跟踪功能。

在JTAG引脚中包含SWD接口引脚,从而允许标准目标连接器中使用。引脚包含:

  • TCLK-SWCLK(串行时钟)
  • TMS-SWDIO(串行数据输入/输出)
  • TDO-SWO(串行线输出-SWV使用)

关于SWV

SWV:Serial Wire Viewer,串行线查看器

基于Cortex-M3、 M4、 M7的设备能够根据所需信息或分析的类型,以多种方式提供高速数据跟踪信息。当系统处理器继续全速运行时,它通过SWO引脚传输。

可从ITM(仪器跟踪宏单元)和DWT(数据观察点和跟踪)单元获得信息,其中包括:

  • PC(程序计数器)采样
  • 显示CPU周期统计信息的事件计数器
  • 具有定时统计信息的异常和中断执行
  • 跟踪数据-用于时序分析的数据读取和写入
  • 用于简单printf样式调试的ITM跟踪信息

拓展:下载调试器

之前给大家分享过《下载调试接口 SWD 和 JTAG的区别》,选择下载调试器时也可以对比一下二者差异。

支持JTAG和SWD模式的下载调试器很多,J-Link、 ST-LINK、 ULINK这些大众化的工具都支持,还有很多小众的下载调试器(比如e-Link、 GD-Link等)同样也支持SWD模式。

那么,我们该选择哪一种呢? 哪一种更香呢?

支持全面的一点的算J-Link了,但正版的价格,对于普通个人来说,有压力。

有多种版本,算下来好几千一个。

“单片机调试时的那些技术"

同样,正版ULINK也和J-Link一样,价格上千。当然,很多人买到的ULINK和J-Link都是盗版。

相比ULINK和J-Link而言,正版的ST-Link价格就很划算,一个正版ST-Link V2才两三百,但缺点就是只能针对STM8/32使用。

当然,ST-Link还有一个神操作:变成J-link,请参看我的文章《手把手教你 ST-Link 秒变 J-link》。

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

围观 169

正常的程序,都不会跳出main,但是,如果跳出了 main 函数,程序到底去哪儿了,你有相关这个问题吗?

一、问题提出

今天在单片机led模块定义函数中看到一个有趣的问题。提问者在进行基本的C51编程实验,编写了一个简单的C51程序如下:

#include <REGX51.H>

void test(num) {
    switch(num) {
        case 1: P2_0=0; P2_1=0; 
            break;
    }
}

void main(void) {
    test(1);
}

程序执行完之后,可以看到实验板上的有两个LED被点亮,另外六个居然微微发亮。

“单片机main函数结束干嘛去了?"

如果在主程序中,增加一个无限循环:while(1); ,则电路板上的就不再会出现“微微点亮”的现象了。

#include <REGX51.H>

void test(num) {
    switch(num) {
        case 1: P2_0=0; P2_1=0; 
            break;
    }
}

void main(void) {
    test(1);
    while(1);
}

“单片机main函数结束干嘛去了?"

上面两种情况的区别,在于第二个程序中主循环 main()函数始终没有退出,而第一个程序,main()函数退出了。似乎前面LED微微点亮 应该与主函数退出之后,单片机都干了些啥有关系。

那么就剩下一个问题:对于普通的嵌入式系统,C语言编程中main()函数退出之后,程序去哪儿了?

二、程序去哪儿了?

从上面提问者书写的代码来看,应该是一位C51的爱好者,使用的是C51的编译器,在一款C51开发板上愉快的进行实验。他一开始没有安装嵌入式程序开发的惯例 在主程序void main(void)中利用无限循环将程序控制在主程序函数中,就出现了前面实验结果中令人迷惑的情况。

“注:他是一个胆大心细的人,观察还挺仔细的。”

2.1 盘古开天辟地

对于C语言编程来说,所有的用户程序世界是从主程序main()开始的。给用户程序开天辟地的任务是由一小段盘古代码STARTUP.A51。

51单片机程序执行流程(STARTUP.A51管理Main函数的执行)

下面截取了STARTUP.A51 代码的一段,可以看到盘古在单片机RESET之后做了点准备工作(初始化全局变量、堆栈指针)之后,就直接跳转至:?C_START

 NAME    ?C_STARTUP

?C_C51STARTUP   SEGMENT   CODE
?STACK          SEGMENT   IDATA

                RSEG    ?STACK
                DS      1

                EXTRN CODE (?C_START)
                PUBLIC  ?C_STARTUP

                CSEG    AT      0
?C_STARTUP:     LJMP    STARTUP1

                RSEG    ?C_C51STARTUP

STARTUP1:

IF IDATALEN <> 0
                MOV     R0,#IDATALEN - 1
                CLR     A
IDATALOOP:      MOV     @R0,A
                DJNZ    R0,IDATALOOP
ENDIF

IF XDATALEN <> 0
                MOV     DPTR,#XDATASTART
                MOV     R7,#LOW (XDATALEN)
  IF (LOW (XDATALEN)) <> 0
                MOV     R6,#(HIGH (XDATALEN)) +1
  ELSE
                MOV     R6,#HIGH (XDATALEN)
  ENDIF
                CLR     A
XDATALOOP:      MOVX    @DPTR,A
                INC     DPTR
                DJNZ    R7,XDATALOOP
                DJNZ    R6,XDATALOOP
ENDIF

IF PPAGEENABLE <> 0
                MOV     PPAGE_SFR,#PPAGE
ENDIF

IF PDATALEN <> 0
                MOV     R0,#LOW (PDATASTART)
                MOV     R7,#LOW (PDATALEN)
                CLR     A
PDATALOOP:      MOVX    @R0,A
                INC     R0
                DJNZ    R7,PDATALOOP
ENDIF

IF IBPSTACK <> 0
EXTRN DATA (?C_IBP)

                MOV     ?C_IBP,#LOW IBPSTACKTOP
ENDIF

IF XBPSTACK <> 0
EXTRN DATA (?C_XBP)

                MOV     ?C_XBP,#HIGH XBPSTACKTOP
                MOV     ?C_XBP+1,#LOW XBPSTACKTOP
ENDIF

IF PBPSTACK <> 0
EXTRN DATA (?C_PBP)
                MOV     ?C_PBP,#LOW PBPSTACKTOP
ENDIF

                MOV     SP,#?STACK-1
                LJMP    ?C_START

                END

上面的代码也被博文51单片机程序执行流程(STARTUP.A51)中进行逐步调试跟踪验证过:

“单片机main函数结束干嘛去了?"

2.2 世界尽头

由于进入main()函数是长跳转,所以main函数是不会正常返回到启动程序STARTUP.A51,那么程序去哪了?

在博文单片机C语言while(1)的问题中作者对于KEIL编译器和PIC的MAPLAB编译器对于main函数的最后时光进行了反汇编查看。

Keil编译器

在main函数的最后,程序增加了一下几行代码:

MOV R0, #0x7F
CLR A
MOV @R0, A
DJNZ R0, (3)
MOV SP, #0x0C
LJMP main

这几条语句,前4条,是将我们单片机的内存的前128个地址清零,第5条,是定义堆栈,第6条,是将程序重新跳转到main函数的首行进行执行。

MAPLAB编译器

PIC 单片机语言程序进行跟踪,发现main() 函数最后一条语句为 reset,也就是单片机直接复位,这是 MAPLAB编译器根据 PIC 单片机特点增加的复位语句。

总结

对于嵌入式系统,如果没有运行RTOS,那么程序开发中的主函数(main())需要通过某种机制使其永远愉快的运行下去,它没有终点。如果想从main函数中退出,具体干什么是由所使用的C语言编译器决定的。

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

围观 27

简介

在过去的二十年里,智能小工具的问世促使电容式触摸表面或触摸板在人机界面(HMI)领域的应用得到了广泛普及。随着业界对触摸需求的日益增长,触摸传感技术也在不断朝着可靠、稳健的方向迈进。因此,对于消费类电子、可穿戴设备、家用电器、家庭自动化、工业、医疗和汽车领域的各种产品而言,电容式触摸界面无疑都是一项必不可少的用户需求。许多设备目前都已使用电容式触摸表面替代机械按钮。

本应用笔记将演示 AVR® DA 单片机的 2D 触摸表面实现,其中使用片上外设触摸控制器(PTC)和 Microchip 触摸库实现集成手势识别。具体将演示 AVR DA 单片机的高级低功耗触摸测量功能,以及如何使用 PTC 外设(令 CPU 处于待机休眠模式)以最大限度地降低功耗。

我们借助 Microchip AVR128DA48 Curiosity Nano、Curiosity Nano 触摸适配器、QT2 Xplained Pro 扩展板和Microchip 触摸库实现了基本的贪吃蛇演示程序来演示 2D 触摸表面手势。补充固件借助 Microchip 的 Atmel START 开发而成,QTouch®配置器(嵌入到 Atmel START 中)用于配置触摸表面参数。

详阅请点击下载《利用外设触摸控制器实现带内置表面手势识别的触摸板》

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

围观 48

单片机开发或多或少都会接触一些汇编代码,今天就来说说关于汇编在C中的定义和调用,以及举例说明嵌套汇编代码。

概述

有认真研究,或者说细心一点的读者应该都知道:C中定义汇编代码与编译器有关。

比如:你在core_cm4.h文件会看到如下的代码:

#if   defined ( __CC_ARM )
  #define __ASM            __asm                                      /*!< asm keyword for ARM Compiler          */
  #define __INLINE         __inline                                   /*!< inline keyword for ARM Compiler       */
  #define __STATIC_INLINE  static __inline

#elif defined ( __GNUC__ )
  #define __ASM            __asm                                      /*!< asm keyword for GNU Compiler          */
  #define __INLINE         inline                                     /*!< inline keyword for GNU Compiler       */
  #define __STATIC_INLINE  static inline

#elif defined ( __ICCARM__ )
  #define __ASM            __asm                                      /*!< asm keyword for IAR Compiler          */
  #define __INLINE         inline                                     /*!< inline keyword for IAR Compiler. Only available in High optimization mode! */
  #define __STATIC_INLINE  static inline

#elif defined ( __TMS470__ )
  #define __ASM            __asm                                      /*!< asm keyword for TI CCS Compiler       */
  #define __STATIC_INLINE  static inline

#elif defined ( __TASKING__ )
  #define __ASM            __asm                                      /*!< asm keyword for TASKING Compiler      */
  #define __INLINE         inline                                     /*!< inline keyword for TASKING Compiler   */
  #define __STATIC_INLINE  static inline

#elif defined ( __CSMC__ )
  #define __packed
  #define __ASM            _asm                                      /*!< asm keyword for COSMIC Compiler      */
  #define __INLINE         inline                                    /*use -pc99 on compile line !< inline keyword for COSMIC Compiler   */
  #define __STATIC_INLINE  static inline
#endif

“单片机C代码嵌套汇编的一些方法"

如果你写过Keil C51,你还会发现有如下(通过预处理)嵌套汇编:

#pragma asm

; Assembler Code Here

#pragma endasm

所以,你会发现,不同的编译器,汇编代码还是有差异。当然,这里主要是说C中嵌套汇编与编译器有关。

C中嵌套汇编代码

常见两种定义:

1.在C函数中定义一段汇编代码;

2.在C文件中定义一个汇编函数;

(当然,两个意思差不多,都是在C中嵌套汇编)

上面说了C中定义汇编代码与编译器有关,换句话说:不同编译器解析汇编代码的方式不同。

这里还是拿core_cm3.c来举例说明,定义一个__get_PSP函数。

在Keil MDK中定义:

__ASM uint32_t __get_PSP(void)
{
  mrs r0, psp
  bx lr
}

在IAR EWARM中定义:

uint32_t __get_PSP(void)
{
  __ASM("mrs r0, psp");
  __ASM("bx lr");
}

__asm(__ASM)关键字用于调用内联汇编程序,并且可在 C 或 C++ 语句合法时出现。

看到这里,推荐阅读我分享的一篇文章:单片机用汇编和C语言点灯程序的区别

举例

下面举一些常见例子。

1.FreeRTOS中portmacro.h文件下源代码:

static portFORCE_INLINE void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;

  __asm
  {
    /* Set BASEPRI to the max syscall priority to effect a critical section. */
    msr basepri, ulNewBASEPRI
    dsb
    isb
  }
}

2.FreeRTOS中port.c文件下源代码:

__asm void xPortPendSVHandler( void )
{
  extern uxCriticalNesting;
  extern pxCurrentTCB;
  extern vTaskSwitchContext;

  PRESERVE8

  mrs r0, psp
  isb

  ldr  r3, =pxCurrentTCB    /* Get the location of the current TCB. */
  ldr  r2, [r3]

  stmdb r0!, {r4-r11}      /* Save the remaining registers. */
  str r0, [r2]        /* Save the new top of stack into the first member of the TCB. */

  stmdb sp!, {r3, r14}
  mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
  msr basepri, r0
  dsb
  isb
  bl vTaskSwitchContext
  mov r0, #0
  msr basepri, r0
  ldmia sp!, {r3, r14}

  ldr r1, [r3]
  ldr r0, [r1]        /* The first item in pxCurrentTCB is the task top of stack. */
  ldmia r0!, {r4-r11}      /* Pop the registers and the critical nesting count. */
  msr psp, r0
  isb
  bx r14
  nop
}

3.内核复位

这是之前分享过的一篇文章《STM32复位来源》中的代码:

__asm void NVIC_CoreReset_a(void)
{
  LDR R0, =0xE000ED0C
  LDR R1, =0x05FA0001
  STR R1, [R0]
deadloop_Core
  B deadloop_Core
}

举了这些常见例子,没有说透,但相信只要认真理解了都能明白。

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

围观 165

页面

订阅 RSS - 单片机