SAM4E单片机之旅——1、LED闪烁之空循环
最近因为导师要写一本关于SAME4单片机的书籍,而我也作为一个嵌入式的初学者看了这本书。现在也让我写写几个小的程序,做做示例。既然写了文档之类的,就发到博客上来吧。
目前关于这芯片能参考的书籍大概就只有英文手册了。用的板子是SAM4E16E。IDE用的是Atmel Studio。既然是学习单片机,就没有使用asf框架,而是直接采用访问寄存器的方法了。
第一个程序就是控制板子上一个LED灯的闪烁了。
一、电路

通过查看电路图,可以发现有一个蓝色的LED灯连接在PA0引脚上。我们可以通过改变PA0输出的电平实现LED灯的闪烁。
二、寄存器的访问和CMSIS
对单片机的操作需要通过对相关寄存器的访问来实现。比如,为调节PA0引脚上的电平,首先我们需要允许PIOA控制PA0引脚。通过查看寄存器说明可知,这只要向相应的PIO使能寄存器(PIO_PER)写入0x01就可以了。同时,也可以查到PIOA的PIO_PER被映射到地址0x400E0E00上了。所以通过如下代码就可以达到目的:
/* 假设 unsigned int长度为32位 */
unsigned int* PIOA_PER_p = (unsigned int*)0x400E0E00u;
(*PIOA_PER_p) = 0x01;
这样做非常繁琐,而且我们也不能保证unsigned int总是32位长。 而且当我们换一块开发板的时候,外设的寄存器地址可能会不同,导致移植起来十分困难。
所以CMSIS出现了。
ARM® Cortex™ 微控制器软件接口标准 (CMSIS) 是 Cortex-M 处理器系列的与供应商无关的硬件抽象层。CMSIS 可实现与处理器和外设之间的一致且简单的软件接口,从而简化软件的重用,缩短微控制器开发人员新手的学习过程,并缩短新设备的上市时间。
软件的创建是嵌入式产品行业的一个主要成本因素。通过跨所有 Cortex-M 芯片供应商产品将软件接口标准化(尤其是在创建新项目或将现有软件迁移到新设备时),可以大大降低成本。
《CMSIS到底是什么》介绍了大概介绍了CMSIS。在这里,我们可以使用它提供的微控制器专用头文件(我们这使用的就是sam.h了),这里提供里外设寄存器的定义,中断号码等:
#include <sam.h>
PIOA->PIO_PER = (uint32_t)0x01;
我们在以后的程序代码中也将使用CMSIS。
三、实现思路
PIO的引脚是复用的,但在这里我们直接使用PIO控制器控制引脚的电平就可以了。可以通过向PIO_SODR、PIO_CODR写入特定的值来直接控制引脚的电平。
然后,通过让程序执行一个次数较长的空循环就可以实现延时功能。
四、代码
实现较为简单,直接看代码就可以了(需要运行Debug模式下产生的代码):
#include <sam.h> int main(void)
{
/* PIO控制器直接控制PA0引脚 */
PIOA->PIO_PER = (uint32_t)0x01;
/* PA0输出使能 */
PIOA->PIO_OER = (uint32_t)0x01;
/* PA0输出写使能 */
PIOA->PIO_OWER = (uint32_t)0x01; while (1) {
/* 设置PA0引脚为高电平,灯灭 */
PIOA->PIO_SODR = (uint32_t)0x01;
/* 延迟 */
for (int i=0; i<1024*1024*2; ++i)
; /* 设置PA0引脚为高电平,灯亮 */
PIOA->PIO_CODR = (uint32_t)0x01;
for (int i=0; i<1024*1024*2; ++i)
;
}
return 0;
}
五、编译器优化的副作用
上面的示例代码中,通过空循环实现延迟的语句出现了两次。很自然的会想到要将这些语句提出成一个函数,甚至可以使用一个参数来大致控制延迟时间的长短:
void Delay(int num)
{
for (int i = 0; i < 1024 * 1024 * num; ++i );
}
然后试着通过这个函数来进行延迟。很遗憾,再运行程序时我们发现LED会一直亮着,而不会闪烁。即使是在Debug模式下,编译器也把这个函数调用给优化掉。类似的情况也会出现不少,这给我们对程序的调试造成一定的不便。 原因是Atmel Studio默认的Debug配置中,使用了O1级别的优化,可以在项目属性中关闭它。
我们试着使用宏来实现这个“函数”:
#define Delay(num) \
do{ \
for (int i = 0; i < 1024 * 1024 * (num); ++i ); \
}while(0)
再运行一下,很好,LED又开始闪烁了。
程序发布的时候,我们一般会使用Release模式生成代码。Atmel Studio使用的gcc编译器果然“不负众望”,把这个空循环语句直接优化掉了。
我们可以使用如下语句阻止编译器的优化:
for (int i = 0; i < 1024 * 1024 * num; ++i )
asm ("");
或者使用volatile关键字:
for (volatile int i = 0; i < 1024 * 1024 * num; ++i ) ;
SAM4E单片机之旅——1、LED闪烁之空循环的更多相关文章
- SAM4E单片机之旅——3、LED闪烁之定时器中断
让一个LED灯闪烁不过瘾,我们应该让这块开发板完成一点更高难度的任务:比如让两个LED灯闪烁. …… 当然了,以我们的现在使用的空循环技术,还是可以实现这点的.但是这样显得略为低端.所以我们使用一个高 ...
- SAM4E单片机之旅——2、LED闪烁之轮询定时器
之前我们使用空循环,达到了延迟的目的,但是这样子的延迟比较不精确.现在就使用实时定时器(RTT)来进行更为精确的计时.RTT虽然不是特别通用,在某些单片机上可能没有,但它较为简单. RTT内部有一个计 ...
- SAM4E单片机之旅——23、在AS6(GCC)中使用FPU
浮点单元(Floating Point Unit,FPU),是用于处理浮点数运算的单元. 为使用FPU,除了需要启用FPU外,还需要对编译器进行设置,以使其针对浮点运算生成特殊的指令.虽然在Atmel ...
- SAM4E单片机之旅——7、LED闪烁之TC中断
RTT主要用做一个全局的定时器,而且不太通用.现在尝试使用一个更为通用的定时器进行定时:定时计数器(Timer Counter, TC). TC提供了广泛的功能,主要可以分为对输入的测量,以及波形的输 ...
- SAM4E单片机之旅——4、LED闪烁之PWM
两个LED灯虽然可以闪了,但是总是需要CPU的参与.现在尝试使用一种更为自动化的方法:让脉宽调制(PWM)控制器输出具有一定周期和占空比的方波,以此控制LED灯的亮灭. 一.实现思路 依然使用蓝色和琥 ...
- SAM4E单片机之旅——6、LED闪烁之按钮控制
现在试试用按钮控制LED灯……让LED在一个按钮按下时亮起:弹起时灭掉. 主要目的是学习GPIO的输入及中断. 一. 电路 图中的J39-n是几个跳线插座,位置在开发板LCD附近,往下进行前要先确保跳 ...
- SAM4E单片机之旅——5、LED呼吸和PWM
PWM在高频情况下,一个很好的用处就是通过控制占空比来控制输出的功率,比如控制风扇转速.LED灯的亮度等.这次就利用PWM的中断功能,动态改变脉冲的占空比,来实现呼吸灯的效果. 一.实现思路 PWM可 ...
- SAM4E单片机之旅——8、UART初步
通信还是比让LED灯闪烁实用得多的. 这次试试使用UART,实现开发版和PC间的通信.功能比较简单,就是把PC发向开发版的内容发送回去.这次主要介绍一下UART的配置,至于通信,则使用较为简单的不断查 ...
- SAM4E单片机之旅——24、使用DSP库求向量数量积
DSP(Digital Signal Processing,数字信号处理)中会使用大量的数学运算.Cortex-M4中,配置了一些强大的部件,以提高DSP能力.同时CMSIS提供了一个DSP库,提供了 ...
随机推荐
- 转 python语法学习面向对象之继承
传送门 python语法学习面向对象之继承 只要涉及到面向对象,”类“是必须出现的一个代名词. 类和对象是面向对象编程的两个主要方面.类创建一个新类型,而对象是这个类的实例. 类的一些概念: 包括初始 ...
- zoj 2760(网络流+floyed)
How Many Shortest Path Time Limit: 10 Seconds Memory Limit: 32768 KB Given a weighted directed ...
- [Inside HotSpot] UseParallelGC和UseParallelOldGC的区别
JVM的很多参数命名很有迷惑性,-XX:+UseParallel,-XX:+UseParallelOldGC,-XX:+UseParNewGC,-XX:+UseConcMarkSweepGC咋一看容易 ...
- 中国正式发放5G牌照 详细对比中美两国5G实力
今天,中国5G商用走进新里程:工信部向中国电信.中国移动.中国联通.中国广电发放5G商用牌照,中国也成为继韩国.美国.瑞士.英国后,第五个正式商用5G的国家. 按照之前的规划,中国原定于2020年开启 ...
- Linux内核源码分析--内核启动之zImage自解压过程
参考: http://blog.chinaunix.net/uid-20543672-id-3018233.html Linux内核编译流程分析 linux2.6内核启动分析--李枝果(不看是你的损失 ...
- UIAlertView弹出视图动画效果
在App设计中为了加强用户体验,我们会常常加入一些友好的动画效果.比如类似UIAlertView弹出的动画效果,由于系统中并没有直接提供类似的动画API,如果我们想要做出一样的效果,那就得深入的研究一 ...
- android权限大全转http://www.cnblogs.com/classic/archive/2011/06/20/2085055.html
android权限大全转http://www.cnblogs.com/classic/archive/2011/06/20/2085055.html 访问登记属性 android.permission ...
- 【sublime text 3】sublime text 3 汉化
快捷键:Ctrl+Alt+P 输入快捷键Ctrl+Shift+P 在出现的文本框中输入Install Package(或直接输入“ip”)选中packageControl:Install Packag ...
- 【GitHub】给GitHub上的ReadMe.md文件中添加图片怎么做 、 gitHub创建文件夹
1.首先在github上的仓库上,创建一个空的文件夹,用于上传图片 上图看 要点击的按钮是创建新的文件,并不是创建新的文件夹,具体怎么?往下看 这个时候,下面的提交按钮才能提交 2.进入新创建的文件夹 ...
- vue生命周期的栗子
vue生命周期的栗子注意触发vue的created事件以后,this便指向vue实例,这点很重要 <!DOCTYPE html><html><head><me ...