IAR for AVR学习笔记
- 格式:pdf
- 大小:368.13 KB
- 文档页数:11
AVR学习笔记前言:学习一块单片机,我们要几项准备工作:1.开发软件(熟悉开发软件操作流程,基本上开发软件都差不多的,学会了一款,再学其它的就会很顺手了(新建工程、新建设计文件、把源文件加到工程里面、最后设置一些参数)2.编程语言(这个就不用说了,先学语法规则,能够熟练掌握到自己写的代码没有语法错误,然后再逐步把自己的想法驾驭到编程语言上)3.硬件(硬件包括的范围很广,不仅包括你所要学的单片机还有单片机的外围电路所用到的器件),最好要学一款仿真软件。
我们始终要记住学单片机绝对不可以纸上谈兵,一定要实践,就是把自己所写的代码下载到板上,看看实际效果。
开发板可以买,也可以自己做!我喜欢自己做。
实验一:点亮发光二极管1.avr单片机的i/o端口1)学习单片机的主要任务就是了解、掌握单片机i/o端口的功能,以及如何正确设计这些端口与外围电路的连接,从而能够组成一个嵌入式系统,并编程、管理和运用他们完成各种各样的任务。
2)atmega16有4个8位的双向i/o端口pa、pb、pc、pd,他们对外对应32个i/o引脚,每一位都可以独立地用于逻辑信号的输入和输出。
在5v工作电压下,输出高点平时,每个引脚可输出达20ma的驱动电流;而输出低电平时,每个引脚可吸收最大为40ma的电流,可以直接驱动发光二极管(一般的发光二极管的驱动电流为10ma)和小型继电器等小功率器件。
avr大部分的i/o端口都具备双重功能(有的还有第三功能)。
其中第一功能是作为数字通用i/o接口使用,而复用的功能可分别与片内的各种不同功能的外围接口电路组合成一些可以完成特殊功能的i/o口,如定时器、计数器、串行接口、模拟比较器、捕捉器、usart、spi等。
3)avr单片机的每组i/o口都搭载存有三个8为寄存器,分别就是:方向掌控寄存器ddrx、数据寄存器portx、输出插槽寄存器pinx(x=a/b/c/d).i/o口的工作方式和整体表现特征由这三个i/o寄存器掌控。
ATmega16中断表第一节课Avr单片机的每个引脚有三个寄存器来控制:DDRnx(输入输出控制寄存器1输出,0输入)PORTnx(引脚输出电平控制)PINnx(输入寄存器)第二节课AVR单片机的AD转换涉及寄存器:ADMUX sbit[7;6]参考电压选择,sbit[5] AD转换数据对齐方式选择,sbit[4:0]通道与增益选择;ADCSRA sbit[7]AD使能,sbit[6]AD开始转换,sbit[5]自动触发使能,sbit[4]AD 中断使能,sbit[3:0]分频设置;SFIOR(触发源的选择)sbit[7:5] (ADTS)选择触发源,ADCL,ADCH数据寄存器;初始化步骤:1:设置通道的IO口为输入(高阻);2:设置与AD有关的寄存器;3:开总中断,SREG=BIT(7);4:写中断函数(中断标号是15)第三节课AVR有三个定时计数器,T/C0,T/C1,T/C2;T/C0,T/C2是两个8BIT的计数器;T/C1定时计数器,普通模式时机寄存器:TCCR1B:2:0时钟选择TCNT1L,TCNTH:定时数据TIMSK :TOIE 中断使能位 使用方法1, 选择时钟源,TCCR1B ;2, 设计初值,TCNT1L ,TCNT1H ;3, 设置中断使能位;TIMSK{2},SREG{7} 4, 选中断号,写中断函数 5, (中断号9)CTC 模式如果输出波形,则设IO 位输出 设置波形模式和时钟源TCCR1B 设置输出模式TCCR1A根据需要设置上限OCR1ATCCR1A 设置输出口频率计算:()A OCR N ffclko112+∙∙=控制寄存器A TCCR1ACOM1A1:0: 通道A 的比较输出模式 COM1B1:0: 通道B 的比较输出模式COM1A1:0与COM1B1:0分别控制OC1A 与OC1B 状态。
如果COM1A1:0(COM1B1:0)的一位或两位 被写入"1”,OC1A(OC1B) 输出功能将取代I/O 端口功能。
原创--IAR for A VR入门学习笔记A VR单片机的编译软件五花八门,用宋丹丹的话就是:那是相当的多汇编语言的开发平台就不说了(俺不大会,呵呵,说不出什么道道来)。
简单列举几个高级语言的开发平台:WINA VR(GNU GCC A VR);ICC A VRCodeVison A VRIAR for A VRBASIC A VRFastA VRBASCOM其中用得最多的是完全免费的WINA VR。
我一直都是用的这个。
最专业,最好的,对AVR支持最全面的是IAR。
但同时IAR也是最贵的一款开发软件(听说升级也要收费,真黑啊)。
呵呵,不过不怕,我们可以破解之。
下面就详细介绍如何破解IAR。
这里安装破解的是5.11B版本的。
全名IAREmbeddedWorkbenchforAtmelAVR,v.5.11B1、先到网上下载5.11B文件,大概133M。
解压后,有如下文件:a1.jpg (29.87 KB)2009-12-20 00:282、到网上下载破解文件解压后生成文件Keygen包,将它复制到C盘根目录下,如下图a2.jpg (63.75 KB)2009-12-20 00:283、打开文件包keygen,双击文件IARID.exe,出现本电脑ID号,如图,记下来a3.jpg (42.68 KB)2009-12-20 00:284、从电脑的“程序---运行”输入“CMD”回车,按照下图操作,得到sn.txt文件;注意输入计算机ID号的时候,所有字符全部大写,包括"0X"中的"X"也要大写,a4.jpg (161.06 KB)2009-12-20 00:285、然后运行安装文件中的autorun.exe,开始安装IAR,当出现要求输入注册号的时候,请用记事本打开刚刚生成的sn.txt 文件,找到"EW A VR" version "2.25_WIN"对应的号码段,先输入序列号,NEXT后,再复制key:后面的一串字符,注意只复制#之前的那一部分,包括#也要复制。
IAR for AVR 学习笔记IAR FOR AVR 学习笔记在AVR编程一直是C,从ICC->GCC->IAR IAR是一个唯一自己选择的.ICC由于入门容易所以选择了开始,GCC因为不要钱,所以后来就用了它.随着对GCC的不断认识,缺点不断显露,开始对IAR产生了兴趣.IAR在51,AVR,ARM的C上都是非常优秀的,它针对不同的单片机都有不同的C版本.唯一一点遗憾的是IAR的价格是个人和小公司难以承受的.当然网上有很多破解,现在的最新版4.20A也有了破解.IAR FOR AVR相关信息:破解方法:ID号注意一定要大写,不然注册将会失败 ,另外并不是每个号都是能用的了,要多试几次.如果注册成功后,编译就会通过.不然就报\没有可的证书\错误. 注意点:如何输出HEX文件?在配置文件后面加入以下代码,便可输出HEX文件,A90文件与HEX文件一样,SLISP都能识别.// Output File-Ointel-extended,(XDATA)=.eep //产生eeprom文件 -Ointel-extended,(CODE)=.A90 //产生烧写文件 -Ointel-extended,(CODE)=.hex //产生烧写文件中断向量的使用IAR中定义中断函数的格式是 ///////////////////////////////// #pragma vector=中断向量__interrupt void 中断服务程序(void) {//中断处理程序 }/////////////////////////////////////中断的初始化要另外加入代码,可在主程序内加入。
如下是各个中断函数的定义。
//中断定义#include#pragma vector=INT0_vect__interrupt void INT0_Server(void) { }#pragma vector=INT1_vect__interrupt void INT1_Server(void) { }#pragma vector=TIMER2_COMP_vect__interrupt void TIMER2_COMP_Server(void) { } #pragma vector=TIMER2_OVF_vect__interrupt void TIMER2_OVF_Server(void) { } #pragma vector=TIMER1_CAPT_vect__interrupt void TIMER1_CAPT_Server(void) { } #pragma vector=TIMER1_COMPA_vect__interrupt void TIMER1_COMPA_Server(void) { } #pragma vector=TIMER1_COMPB_vect__interrupt void TIMER1_COMPB_Server(void) { } #pragma vector=TIMER1_OVF_vect__interrupt void TIMER1_OVF_Server(void) { } #pragma vector=TIMER0_OVF_vect__interrupt void TIMER0_OVF_Server(void) { } #pragma vector=SPI_STC_vect__interrupt void SPI_STC_Server(void) { }#pragma vector=USART_RXC_vect__interrupt void USART_RXC_Server(void) { } #pragma vector=USART_UDRE_vect__interrupt void USART_UDRE_Server(void) { } #pragma vector=USART_TXC_vect__interrupt void USART_TXC_Server(void) { } #pragma vector=ADC_vect__interrupt void ADC_Server(void) { }#pragma vector=EE_RDY_vect__interrupt void EE_RDY_Server(void) { }#pragma vector=ANA_COMP_vect__interrupt void ANA_COMP_Server(void) { }#pragma vector=TWI_vect__interrupt void TWI_Server(void) { }#pragma vector=INT2_vect__interrupt void INT2_Server(void) { }#pragma vector=TIMER0_COMP_vect__interrupt void TIMER0_COMP_Server(void) { }#pragma vector=SPM_RDY_vect__interrupt void SPM_RDY_Server(void) { }如何把常数字符串定义在flash 空间?法一:unsigned char __flash temptab[] = {1,2,3,4,5}; 法二:__flashunsigned char temptab[] = {1,2,3,4,5}; 法三:#pragma type_attribute=__flash unsigned char temptab[]={1,2,3,4,5};法四:const unsigned char temptab[]={1,2,3,4,5};注:第三种方式用#pragma说明后,下面的定义的变量将都在FLASH空间了,用于定义一批FLASH变量,但实际上一般只能作为常量使用了.感谢您的阅读,祝您生活愉快。
AVR 单片机一些学习笔记
下面是自己在学习AVR 单片机时的学习经验,分享出来给大家,一起
学习。
1、AVR 单片机采用RISC 架构,8051 单片机采用CISC 架构。
前者速度为后者的2~4 倍,为流水线操作指令。
2、AVR 单片机有32 个通用寄存器(地址在RAM 区从$0000 开始到$001F),其中有6 个(最后6 个)合并为3 个16 位的X,Y,Z 寄存器,用来存放地址指针,Z 寄存器还可以寻址程序存储器。
3、哈佛结构,131 条机器指令。
4、延迟开机功能。
5、内部自带RC 振荡器,可提供1/2/4/8MHZ 的工作时钟。
6、FLASH+EEPROM+SRAM+SPI+USART+TWI+PWM+RTC+10 位ADC+模拟比较器+JTAG。
7、堆栈指针向下增长,51 单片机向上增长。
8、程序存储器按字来访问,擦除和写入以页为单位。
一、AVR单片机位操作
(1)置位。
要将R的第3位置1,其他位不变,可以这样做:R |= (1<<3),其中“1<<3”
的结果是“0b00001000”,R |= (1<<3)也就是R=R|0b00001000,任何数和0相或不变,任何数和1相或为1,这样达到对R的第3位置1,但不影响其他位的目的。
(2)清位。
要将R的第2位清0,其他位不变,可以这样做:R &= -(1<<2),其中“-(1<<2)”
的结果是“0b11111011”,R&=-(1<<2)也就是R=R&0b11111011,任何数和1相与不变,任何数和0相与为0,这样达到对R的第2位清0,但不影响其他位的目的。
(3)获得某一位的状态。
(R>>4) & 1,是获得R第4位的状态,“R>>4”是将R右移4位,将R的第4位移至第0位,即最后1位,再和1相与,也就是和0b00000001相与,保留R最后1位的值,以此得到第4位的状态值。
二、AVR单片机中断向量表
三、AVR单片机引脚图。
A VR学习笔记十四、模块化程序设计(二)14.1 程序模块化设计(二)14.1.1、实例功能在前面一讲里,我们已经初步了解了模块化程序设计的简单知识,今天我们再深入探讨一下模块化程序设计。
我们先回顾一下前面一讲的主要内容:模块化程序设计是指将实现同一功能的程序整合起来,封装到一个程序模块中,这样在使用该功能的时候,可以直接调用该模块中的相关函数进行操作。
我们在单片机编程中经常用到的按键检测、液晶显示、数码管显示、串口通信、DS18B20温度检测、DS1302实时时钟等经常用到的程序都可以实现模块化。
模块化编程的最大优点是:思路清晰、移植方便、程序简化。
通常的做法是将某一模块中所有用到的端口定义,函数声明,函数定义等一起写到一个“.h”或者“.c”文件中,然后在主程序里面使用“#include”预编译指令将这些内容包含到主程序中,这样做调用虽然简单,但是对于模块化程序设计来说还是显得有些不太直观,因为我们调用模块中的函数的时候,需要在这一个模块文件中很费劲的找出需要的函数。
同样对于移植到别的单片机系统中的时候,需要遍历该模块文件,然后一一更改。
如果不小心,很容易造成错误。
更为标准的做法是我们将某一个功能模块的端口定义,函数声明这些内容放在一个“.h”文件中,而把具体的函数实现(执行具体操作的函数)放在一个“.c”文件中。
这样我们在编写主程序文件的时候,可以直接使用“#include”预编译指令将“.h”文件包含进主程序文件中,而在编译的时候将“.c”文件和主程序文件一起编译。
这样做的优点是,我们可以直接在“.h”文件中查找到我们需要的函数名称,从而在主程序里面直接调用,而不用去关心“.c”文件中的具体内容。
如果我们要将该程序移植到不同型号的单片机上,我们同样只需在“.h”文件中修改相应的端口定义即可。
在这一讲中,我们继续学习一下模块化程序设计。
本实例有两个功能模块:●继续了解模块化程序设计的思路和方法。
PC = progammer counter //程序计数器ACC = accumulate //累加器PSW = progammer status word //程序状态字SP = stack point //堆栈指针DPTR = data point register //数据指针寄存器IP = interrupt priority //中断优先级IE = interrupt enable // 中断使能TMOD = timer mode //定时器方式 (定时器/计数器控制寄存器)ALE = alter (变更,可能是)PSEN = progammer saving enable //程序存储器使能(选择外部程序存储器的意思) EA = enable all(允许所有中断)完整应该是 enable all interruptPROG = progamme (程序)SFR = special funtion register //特殊功能寄存器TCON = timer control //定时器控制PCON = power control //电源控制MSB = most significant bit//最高有效位LSB = last significant bit//最低有效位CY = carry //进位(标志)AC = assistant carry //辅助进位OV = overflow //溢出ORG = originally //起始来源DB = define byte //字节定义EQU = equal //等于DW = define word //字定义E = enable //使能OE = output enable //输出使能RD = read //读WR = write //写中断部分:INT0 = interrupt 0 //中断0INT1 = interrupt 1//中断1T0 = timer 0 //定时器0T1 = timer 1 //定时器1TF1 = timer1 flag //定时器1 标志 (其实是定时器1中断标志位)IE1 = interrupt exterior //(外部中断请求,可能是)IT1 = interrupt touch //(外部中断触发方式,可能是)ES = enable serial //串行使能ET = enable timer //定时器使能EX = enable exterior //外部使能(中断)PX = priority exterior //外部中断优先级PT = priority timer //定时器优先级PS = priority serial //串口优先级第一部分二极管发光的条件是正负极相差达1V以上。
A V R单片机嵌入式系统原理与应用实践——学习笔记AVR单片机嵌入式系统原理与应用实践学习笔记1.AVR单片机的基本结构1.1.单片机的基本组成1.1.1.单片机的基本组成结构单片机的基本组成单元➢CPU➢程序存储器➢数据存储器➢I/O接口CPU与各基本单元通过芯片内的内部总线连接。
一般情况下,内部总线中的数据总线宽度(或指CPU字长)也是单片机等级的一个重要指标。
内部总线:数据总线、地址总线、控制总线。
1.1.2.单片机的基本单元与作用1)MCU单元MCU单元部分包括CPU、时钟系统、复位、总线控制逻辑等电路。
➢CPU:➢时钟和复位电路:➢总线控制电路:2)片内存储器单片机的存储器一般分为程序存储器和数据存储器,它们往往构成互不相同的两个存储空间,分别寻址,互不干扰。
单片机的内部结构通常使用哈佛体系结构,在这种体系中采用分开的指令和数据总线以及分开的指令和数据空间,分别采用专用的总线与CPU交换,可以实现对程序和数据的同时访问,提高了CPU的执行速度和数据的吞吐量。
3)程序存储器程序存储器用于存放嵌入式系统的应用程序。
4)数据存储器单片机在片内集成的数据存储器一般有两类:随机存储器RAM、电可擦除存储器EEPROM。
➢随机存储器RAM:➢电可擦除存储器EEPROM5)输入输出端口➢并行总线I/O端口:➢通用数字I/O端口:➢片内功能单元的I/O端口:➢串行I/O通信口:➢其他专用接口:6)操作管理寄存器管理、协调、控制、操作单片机芯片中各功能单元的使用和运行。
1.2.ATmega16单片机的组成1.2.1.AVR单片机的内核结构“快速访问”意味着在一个周期内执行一个完整的ALU操作。
AVR的算术逻辑单元ALU支持寄存器之间、立即数与寄存器之间的算术与逻辑运算功能,以及单一寄存器操作。
每一次运算操作的结果将影响和改变状态寄存器(SREG)的值。
ALU操作➢从寄存器组中读取两个操作数➢将执行结果写回目的寄存器➢操作数被执行1.2.2.ATmega16的外部引脚与封装I/O引脚共32只,分成PA、PB、PC、PD4个8位端口,它们全部是可编程控制的多功能复用的I/O引脚。
A VR学习笔记二、基本输入和外部中断实验-------基于LT_Mini_M162.1 利用按键控制发光二极管的亮灭2.1.1 实例功能在“点亮发光二极管”和“让发光二极管动起来”这两个例子中,都是通过单片机程序来控制发光二极管的亮灭。
如果想要控制发光二极管的亮灭,只有通过打开或者关闭电源来实现控制。
那么怎样实现人工参与控制呢?在有些应用场合,需要单片机对人工的开关信号作出相应的响应和处理,通过控制电源的通断会影响到单片机系统中的其他功能,所以通过控制电源的方法并不明智。
能不能通过按动一个按键来实现发光二极管的亮灭呢?当然可以,前面已经讲过,A VR单片机的I/O口都是双向的,也就是既能当作输出控制端口,也能当作输入检测端口。
既然我们可以通过控制端口输出不同的高低电平使发光二极管实现点亮和熄灭;那么为什么不能通过监测端口输入电平的状态来进行相应的处理呢。
在本例中,通过介绍利用按键开关控制发光二极管的亮灭来了解A VR单片机的端口检测外部信号的功能和方法。
本例中有3个功能模块,描述如下:●单片机系统:检测外界的按键开关信号,根据按键的开关状态控制发光二极管的亮灭状态。
●外围电路:首先是产生信号的按键电路,包括对按键去抖动电路的介绍;然后是发光二极管的控制电路。
●软件程序:通过读取AVR单片机相应端口的状态,编写相应的程序控制发光二极管的亮灭。
本例的目的在于希望读者完成本例后,能完成相关电路的设计和相应程序的编写,从而掌握以下知识点:◆了解AVR单片机端口输入功能,掌握使用AVR单片机端口输入功能检测外部信号的原理。
◆熟悉单片机端口输入输出功能的综合使用。
◆掌握AVR单片机按键的硬件去抖动的电路设计和原理。
◆掌握AVR单片机端口输入输出程序的编写。
◆掌握AVR单片机按键软件去抖动功能的实现。
2.1.2 器件和原理本例主要介绍A VR单片机外围电路中按键去抖电路的设计,分别介绍相应的软件和硬件解决方案。
大家好,写这个文档是想教你们如何写出单片机的第一个程序,同时对比一下单片机的C语言和你们在Visual Studio下编写的C语言的不同之处。
单片机编程也是用C语言,但是跟PC上编写风格还是有一些不同,大家要注意。
首先大家看一段十分简单的PC上的C语言程序。
#include <stdio.h>void main(void){int a = 1, b = 2, c = 3;int sum = 0;sum = a + b + c;printf("%d\n",sum);}大家再看一段十分简单的单片机C语言程序。
为了方便,我把PC上的C语言称为“C语言”,把单片机上的C语言称为“C51语言”。
/*****************************************************This program was produced by theCodeWizardAVR V1.25.9 ProfessionalAutomatic Program Generator?Copyright 1998-2008 PavelHaiduc, HP InfoTech s.r.l.Project :Version :Date : 2011/9/10Author : ZHOUQIANCompany : ZHOUQIANComments:Chip type : ATmega88P //AVR芯片型号Program type : ApplicationClock frequency : 7.372800 MHz //晶振频率Memory model : SmallExternal SRAM size : 0Data Stack size : 256*****************************************************/#include <mega88p.h> //该头文件定义了寄存器#include <delay.h> //该头文件引入延时函数void main(void){DDRD.6 = 1; //什么是DDRD?PORTD.6 = 0; //什么是PORTD?while (1) //while(1)是死循环,为什么会用它?{PORTD.6 = 1; //LED亮delay_ms(1000); //为什么要延时?PORTD.6 = 0; //LED灭delay_ms(1000);}}大家很容易观察发现,C语言习惯设一些变量,例如int a,b,c,然后对这些变量进行读写,而C51却对DDRD和PORTD进行读写,DDRD和PORTD是寄存器,AVR大概有60个寄存器,通过操作它们我们可以控制AVR芯片的某个引脚输出高电平或低电平,可以让某个引脚检测外部输入了什么电平或边沿,可以让单片机和别的设备互相收发信号,可以让单片机测出某个引脚上输入的电压值,可以让某个引脚发出特定频率和占空比的波形来控制电机,等等。
A VR单片机笔记说明:主要使用的编译环境为IAR,使用A VR的ATmega16 和128目录IO (2)时钟: (2)MCU控制寄存器-MCUCR (2)MCU控制和状态寄存器-MCUCSR (2)看门狗定时器控制寄存器-WDTCR (3)外部中断控制寄存器A -EICRA (4)外部中断控制寄存器B -EICRB (4)外部中断屏蔽寄存器-EIMSK (4)外部中断标志寄存器-EIFR (5)中断矢量表 (5)在IAR环境中AVR中断程序的格式 (6)定时器 (6)定时器/计数器0和2: (6)定时器/计数器1和3: (7)使用IAR调试注意事项 (7)IIC(TWI) (8)o8515.h头文件 (10)IOPort A-G:都含有内部上拉电阻数据:PORTA-G;方向DDRA-G;PINA-G 时钟:XTAL 分频控制寄存器-XDIVMCU控制寄存器-MCUCRMCU控制和状态寄存器-MCUCSR• Bit 4 – JTRF: JTAG 复位标志通过JTAG 指令A VR_RESET 可以使JTAG 复位寄存器置位,并引发MCU 复位,并使JTRF 置位。
上电复位将使其清零,也可以通过写”0” 来清除。
• Bit 3 – WDRF: 看门狗复位标志看门狗复位发生时置位。
上电复位将使其清零,也可以通过写”0” 来清除。
• Bit 2 – BORF: 掉电检测复位标志掉电检测复位发生时置位。
上电复位将使其清零,也可以通过写”0” 来清除。
• Bit 1 – EXTRF: 外部复位标志外部复位发生时置位。
上电复位将使其清零,也可以通过写”0” 来清除。
• Bit 0 – PORF: 上电复位标志上电复位发生时置位。
只能通过写”0” 来清除。
看门狗定时器控制寄存器-WDTCR• Bits 7..5 – Res: 保留保留位,读操作返回值为零。
• Bit 4 – WDCE: 看门狗修改使能清零WDE 时必须先置位WDCE,否则不能禁止看门狗。
在AVR 所有的编译器中,IAR for AVR 是编译效率最高的编译器, 但是相对来说IAR for AVR 的设置项也非常多,如果使用不当反而会出现很多莫名其妙的问题.一. 关于堆栈的设置问题GCC 和IAR 分配堆栈的方式不同,IAR 先分配堆栈空间,相当于定义一个全局数组为堆栈空间,堆栈初始为堆栈空间最高地址;GCC 不用先分配堆栈,自动把RAM 剩余空间作为堆栈空间,堆栈初始为RAM 最高地址。
初学者很容易忽视这个问题,造成程序跑飞而找不到问题的症结,我在用IAR For MSP430 的时候没遇到过这个问题,因为MSP430 的RAM 比较大,IAR 默认是80 字节,足够一般程序使用。
但是使用IAR For SAM8 的时候,有一个比较耗费堆栈的程序运行一段时间后出问题,由于要记录一个24 小时的数组,而数组元素的值是在堆栈里改变的,所以,记录到一定时间以后,出现了堆栈不足的情况,初学者如果没有仿真器,是很难发现这个问题的,还好我用的OPENice i500 仿真器在Debug 的时候出现了堆栈不足的警告,我才意识到是这里问题。
IAR For SAM8 默认堆栈是32 字节,既然不够用,那么就要增大,但是设置到多少合适呢?首先编译你的程序,看程序用了多少自己的RAM,在看看芯片的Datasheet,看看芯片总共有多大的RAM,(原文件名:9428.JPG) 引用图片好了现在你就知道剩余多少RAM 了:208-142=66(Byte)前面说过IAR 的CSTACK,NEAR_HEAP 和RSTACK 是预先分配好的,占用存储空间是固定不变的,相当于定义了一个全局数组,GCC 堆栈策略与IAR 不同,堆栈大小不是预先分配好的,而是把SRAM 里面剩余空间作为堆栈空间。
如果是GCC,那么编译器就会自动设置剩余的RAM 为数据堆栈(和数据返回堆栈RSTACK,NEAR_HEAP 等)。
在IAR 里,STACK 应该设置到多少呢?在工程-》Options-》Linker-》List(不同的IAR 版本会稍有不同),选择生成LIST 文件,并包含stack 选项(原文件名:iar.JPG) 引用图片在./Debug/list 目录下,得到.map(可能是.lst 等其他格式)文件,用记事本打开,找到以下内容:******************************************* CALL GRAPH******************************************* ->Sub-tree of type: Interrupt function tree that does not make: indirect callsCSTACK01Stack used (prev) :int_T0_OV00000000| Stack used (prev) : 00000000 | + function block : 0000000C......(省略N 行)01 main| Stack used (prev) : 0000003A| + function block : 00000000<-Sub-tree of type: Function tree| Stack used : 0000003A找到最大的Stack used,我的就是0000003A,58 个字节,这就是用到的最大的堆栈空间,保守一点,我设置成64 字节,没有超过剩余RAM,再重新编译,运行,仿真器没有堆栈不足警告,程序也能正常运行了。