AVR C语言的应用Word下载.docx
《AVR C语言的应用Word下载.docx》由会员分享,可在线阅读,更多相关《AVR C语言的应用Word下载.docx(25页珍藏版)》请在冰豆网上搜索。
![AVR C语言的应用Word下载.docx](https://file1.bdocx.com/fileroot1/2022-11/23/fa98bcec-9fe0-4963-91a5-cfac9817ec33/fa98bcec-9fe0-4963-91a5-cfac9817ec331.gif)
–Zero标志的传播
SUBR16,R24SUBIR16,1
SBCR17,R25SBCIR17,0
所有的跳转都基于最后结果
两个16位数相减
Non-destructivecomparison
CPR16,R24
CPCR17,R25
CPCR18,R26
CPCR19,R27
•带进位比较
•Zero传播
•无需保存结果
•可使用所有形式的跳转
Switch支持
•Switches在CASE语句中经常遇到
•Straightforwardapproach效率低
•间接跳转适合于紧凑的switch结构
•switch由通用库管理
摘要
•AVR结构从一开始就是针对高级语言设计的
•Atmel与IAR在结构和指令调整上的合作
•从而编译器可以产生高效的代码
EfficientC-codingforAVR
减少代码的提示和诀窍
汇编(Assembly)与C比较
汇编:
•可以完全控制资源
•在小应用当中可以产生紧凑的、高速的代码
•在大的应用当中代码效率低
•可读性差(Crypticcode)
•不好维护
•不易移植(Non-portable)
C:
•对资源的控制有限
•在小应中产生的代码量大,执行速度慢
•在大的应用当中代码效率高
•结构化的代码
•容易维护
•容易移植
访问I/O
•读I/O:
temp=PIND;
INR16,LOW(16)
•写I/O:
TCCR0=0x4F;
LDIR16,79
OUTLOW(51),R16
•I/O的位设置与清除
•地址小于0x1F的I/O:
PORTB|=(1<
PIND2);
SBILOW(24),LOW
(2)
ADCSR&
=~(1<
ADEN);
CBILOW(6),LOW(7)
•地址高于0x1F的I/O:
TCCR0&
=~(0x80);
INR16,LOW(51)
ANDIR16,LOW(127)
OUTLOW(51),R16
测试I/O的单个位
•等待地址低于0x1F的单个位的清除
while(PIND&
(1<
PIND6));
SBICLOW(16),LOW(6)
RJMP?
0002
•等待地址高于0x1F的单个位的设置
while(!
(TIFR&
TOV0)));
INR16,LOW(56)
SBRSR16,LOW(0)
0004
16位变量
•总是使用最小的数据类型
•8位计数器:
charcount8=5;
do{
}while(--count8);
LDIR16,5
DECR16
BRNE?
•Total6bytes
•16位计数器:
intcount16=5;
}while(--count16);
LDIR24,LOW(5)
LDIR25,0
SBIWR24,LWRD
(1)
Total8Bytes
全局和局部变量
•全局变量
–在startup初始化
–存储于SRAM
–必须加载到寄存器堆中
•局部变量
–在函数初期初始化
–存储于寄存器当中直至函数结束
全局变量和局部变量
•局部变量
voidmain(void)
{
charlocal;
local=local-34;
}
SUBIR17,LOW(34)
•Total2bytes
•全局变量
charglobal;
global=global-45;
LDSR16,LWRD(global)
SUBIR16,LOW(45)
STSLWRD(global),R16
Total10Bytes
高效地使用全局变量
•将全局变量收集到一个结构中:
typedefstruct{
intt_count;
charsec;
//globalseconds
charmin;
//globalminutes
}t;
ttime;
Voidmain(void)
t*temp=&
time;
temp->
sec++;
min++;
t_count++;
带参数的函数调用
•使用参数将数据传递到函数中去
charadd(charnumber1,charnumber2)
{
returnnumber1+number2;
函数间参数的传递通过R16-R23来实现
循环
•死循环
for(;
;
)
}
•循环
charcounter=100;
do{
}while(--counter);
预减变量(Pre-decrement)代码效率最高
优化代码的选项
•代码大小优化编译
•使用局部变量
•使用允许的最小数据类型
•将全局变量收集到结构中去
•死循环使用for(;
;
)
•使用预减的do{}while;
CAVR的程序设计
程序设计的程序设计
内容
•安装必须的工具
9.2C编译的介绍
•练习
边学边做
•用C编程
–设置编译和链接文件
–用C访问外围
–中断处理
–高级调试
•使用不同的AVR外围
–定时器/计数器
–UART
–外部中断
Toolflow
•器件:
AT90S8535
•CCompiler
•AVRstudio——仿真
•STK200——测试代码
•测试程序:
死循环
–读PortD的值(按键,输入口)
–将其值写到PortB(LED,输出口)
测试程序
#include<
io8515.h>
/*定义AT90S8515*/
charc;
DDRB=0xFF;
/*PortBalloutputs*/
for(;
)/*Eternalloop*/
{
c=PIND;
/*ReadPortD*/
PORTB=c;
/*回写到PortB*/
}
安装C编译器
•CompilerdeliveredonCD-ROM
•安装Dongle驱动器(见“DONGLE.TXT”)
设置C编译器
•启动IAREmbeddedWorkbench
可双击快捷图标
•创建新工程
–File->
New->
Project:
设置编译器选项
Project->
Options
•设置链接器文件XLINK
•选择“Release”
•选择处理器配置及内存模式
•设定“intel-extended”为输出格式(releaseonly)
•将文件加入到工程-Project->
Files...
•设定“Debug”为当前配置
•“Make”theprogram:
–Project->
Make
–PressF9
–Toolbutton
带调试信息的可执行文件在DEBUG\EXE目录
使用AVRStudio
•启动AVRStudio
•加载调试文件(TestProg.d90)-File->
Open
•选择AT90S8515(只需在开始时选择一次)
•加入视图(VIEW)
–I/O(PinB,PortD)
–Processor
–Watch
»
c
PORTB
PIND
•单步执行,TogglePINDbits
对器件编程
•选择编程窗口
•加载Intel-Hex文件(TestProg.hex)-File->
Load
•对器件编程
–Program->
Autoprogram
–F5
–Pushbutton
9.3测试应用程序
Main函数
•“main”是所有C程序的入口点
•不要加入参数,也不要返回值
•语法:
voidmain(void)
/*代码*/
访问外围
•所有I/O寄存器在头文件里都被定义为特殊功能寄存器
•象普通变量一样访问
/*定义8515*/
DDRD=0xFF;
/*PortD输出*/
9.3.1读/写口
/*PortB输出*/
)/*死循环*/
/*读PortD*/
9.3.2延时函数
voiddelay(unsignedintdelayValue)
unsignedinti;
for(i=0;
i<
delayValue;
i++)/*循环*/
;
/*Donothing*/
9.3.2A:
延时函数
unsignedcharrunner=0x01;
DDRB=0xff;
/*PortB输出*/
for(;
)/*死循环*/
if(runner)runner<
=1;
elserunner=0x01;
PORTB=runner;
/*设置LED*/
delay(100);
/*调用延时函数*/
9.3.3读/写E2PROM
/*利用IAR标准I/O函数来读/写E2PROM*/
ina90.h>
chartemp=0;
_EEPUT(0x10,temp);
/*写E2PROM地址:
0x10*/
_EEGET(temp,0x10);
/*读E2PROM地址:
0x10*/
9.3.4AVR的PB口变速移位
/*文件名:
SLAVR934.ASM*/
/*位运算符:
~按位取反;
<
左移;
>
右移;
&按位与;
∣按位或;
^按位异或;
i++相当于i=i+1;
i--相当于i=i-1*/
/*器件配置文件*/
#defineBIT(x)(1<
(x));
/*左移*/
voiddelay(void)
unsignedchari,j;
for(i=1;
i;
i++)
for(j=1;
j;
j++);
voidled_pb(void)
unsignedchari;
DDRB=0xff;
/*设PB口输出*/
for(i=0;
8;
i++)/*硬件设定低电平灯亮,LED的1位亮灯从B口PB0→PB7*/
PORTB=~BIT(i);
/*LED亮灯1位*/
delay();
/*延时*/
voidmain(void)/*主函数*/
while
(1)/*循环*/
led_pb();
9.3.54个口LED亮灯变速移位
SLAVR935.ASM*/
/*请修改程序,改变移位方向,2位或3位或一隔一亮灯移位等*/
/*预处理命令,头文件*/
(x))?
*定义位函数,可修改移位方向*/
voiddelay(unsignedchart);
/*延时函数*/
unsignedcharj;
t;
voidled_pb(unsignedchart);
/*LED移位函数*/
/*设PB口为输出*/
i++)/*硬件设定低电平灯亮,LED的1位亮灯从B口PB0→PB7*/
/*LED亮灯1位*/
delay(t);
/*延时*/
PORTB=0xff;
/*关PB口*/
voidled_pd(unsignedchart);
/*LED的1位亮灯从D口PD0→PD7移位函数*/
DDRD=0xff;
i++)/*LED的1位亮灯从D口PD0→PD7*/
PORTD=~BIT(i);
PORTD=0xff;
voidled_pc(unsignedchart);
/*C口PC0→PC7移位函数*/
DDRC=0xff;
i++)/*LED的1位亮灯从C口PC0→PDC*/
PORTC=~BIT(i);
PORTC=0xff;
voidled_pa(unsignedchart);
/*A口PA7→PA0移位函数*/
DDRA=0xff;
for(i=8;
i>
0;
i--)/*LED的1位亮灯从A口PA7→PA0*/
PORTA=~BIT(i-1);
PORTA=0xff;
voidmain(void);
/*主函数*/
unsignedchardt;
for(dt=5;
dt<
200;
dt+=25)
led_pb(dt);
/*LED发光二极管一亮灯沿四个口移位变速循环*/
led_pd(dt);
led_pc(dt);
led_pa(dt);
}
9.3.6音符声程序
/*源程序SLAVR936.ASM*/
/*可改变t函数,改变发音快慢*/
/*预处理命令*/
#defineucharunsignedchar
#defineuintunsignedint
voiddelay(uchart)
uchari,j;
j<
150;
voidsound_pc0(uchart)
uinti;
350-t*t;
i++)/*改变发音快慢,另见SLAVR936B.ASM程序*/
PORTC^=(1<
0);
voidmain(void)/*主函数*/
uchardt;
for(;
)
for(dt=1;
14;
dt++)/*改变发音数量*/
sound_pc0(dt);
9.3.78字循环移位显示程序
/*源程序SLAVR937.ASM*/
/*在SL-AVR开发实验器LED数码管上,8字符循环移位显示程序*/
/*器件配置文件*/
#defineucharunsignedchar/*定义缩写*/
#defineuintunsignedint
voiddelay(uintt)
i++);
voidinit_disp(void)/*B口,D口初始化*/
PORTB=0x7f;
/*B口送8字符,字形可修改*/
voidscan(void)/*位选扫描*/
6;
i++)/*i++可修改为一位隔一位或隔2位显示或改变移位方向*/
j=150;
/*可改变移位速度*/
do
{
PORTD=~(0x01<
i);
delay(150);
/*可改变LED显示亮度*/
delay(2100);
while(--j);
voidmain(void)/*主程序*/
init_disp();
/*初始化*/
scan();
/*位选扫描*/
9.3.8按键加1计数显示程序
/*在SL-AVR开发实验器上,用SHIFT键,按1次键加1计数显示程序*/
/*头文件*/
#defineucharunsignedchar/*缩写定义*/
flashucharDATA_7SEG[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
/*LED字形表*/
ucharled[6];
/*显示缓冲*/
uintcount;
/*延时子程序*/
voidinit_disp(void)/*初始化B口,D口*/
DDRD=0x7f;
PORTD|=0x80;
voiddisp(void)/*键盘显示*/
uchari;
PORTB=DATA_7SEG[led[i]];
delay(1000);
PORTB=0x00;
voidbe_pc0(void)/*发出一声响子程序*/
DDRC|=0x01;
350;
PORTC^=0x01;
delay(350);
voidconv(void)/*计数值转换成十进制数*/
led[5]=0;
led[4]=count/10000;
led[3]=count/1000%10;
led[2]=count/100%10;
led[1]=count/10%10;
led[0]=count%10;
init_disp();
/*初始化B口,D口*/
count=0;
/*开始计数值是零*/
conv();
/*转换*/
while((PIND&
0x80)==0x80)/*没有键按下等待*/
disp();
/*显示*/
be_pc0();
/*发出一声响*/
count++;
/*计数器加1*/
conv();
/*转换成十进制数*/
0x80)==0)/*有键按下*/