AVR C语言的应用.docx

上传人:b****3 文档编号:3506957 上传时间:2022-11-23 格式:DOCX 页数:25 大小:285.08KB
下载 相关 举报
AVR C语言的应用.docx_第1页
第1页 / 共25页
AVR C语言的应用.docx_第2页
第2页 / 共25页
AVR C语言的应用.docx_第3页
第3页 / 共25页
AVR C语言的应用.docx_第4页
第4页 / 共25页
AVR C语言的应用.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

AVR C语言的应用.docx

《AVR C语言的应用.docx》由会员分享,可在线阅读,更多相关《AVR C语言的应用.docx(25页珍藏版)》请在冰豆网上搜索。

AVR C语言的应用.docx

AVRC语言的应用

第九章AVRC语言的应用

★更详细资料参阅光盘文件<>

9.1AVR–支持C和高级语言编程的结构

高级语言

•提高了MCU的重要性

–上市的时间

–简化维护工作

–轻便

–学习时间

–可重用性

–库

•潜在的缺点

–代码大小

–执行速度

为什么AVR适宜用高级语言编程?

因为它是为高级语言而设计的!

IAR对AVR结构和指令集的影响

•在结构/指令集确定之前,编译器的开发就开始了

•潜在的瓶颈得到确认并消除

•IAR的反馈在硬件设计上得到了反映

•几次循环反复

•修改后的结果从代码当中可看出来

Memorysystem

•32通用寄存器

–数量多

–直接与ALU连接

–可保存变量,指针和之间结果

•线性程序存储空间

–1KBytes-8MBytes

–无需页寻址

–常数区(SPM可修改)

•线性数据存储空间

–16MBytes

–无需页寻址

类似于C的寻址模式

C源代码

unsignedchar*var1,*var2;

*var1++=*--var2;

产生的代码

LDR16,-X

STZ+,R16

带偏移量的间接寻址

•有效访问数组和结构

•Auto(localvariables)放置于软件堆栈之中

–为适应重入的要求,高级语言都基于堆栈结构

 

四种指针

16和32位支持

•加法指令

–加和减

–寄存器之间

–寄存器和立即数之间

–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<

SBILOW(24),LOW

(2)

ADCSR&=~(1<

CBILOW(6),LOW(7)

•地址高于0x1F的I/O:

TCCR0&=~(0x80);

INR16,LOW(51)

ANDIR16,LOW(127)

OUTLOW(51),R16

测试I/O的单个位

•等待地址低于0x1F的单个位的清除

while(PIND&(1<

SBICLOW(16),LOW(6)

RJMP?

0002

•等待地址高于0x1F的单个位的设置

while(!

(TIFR&(1<

INR16,LOW(56)

SBRSR16,LOW(0)

RJMP?

0004

16位变量

•总是使用最小的数据类型

•8位计数器:

charcount8=5;

do{

}while(--count8);

LDIR16,5

DECR16

BRNE?

0004

•Total6bytes

•16位计数器:

intcount16=5;

do{

}while(--count16);

LDIR24,LOW(5)

LDIR25,0

SBIWR24,LWRD

(1)

BRNE?

0004

Total8Bytes

全局和局部变量

•全局变量

–在startup初始化

–存储于SRAM

–必须加载到寄存器堆中

•局部变量

–在函数初期初始化

–存储于寄存器当中直至函数结束

 

全局变量和局部变量

•局部变量

voidmain(void)

{

charlocal;

local=local-34;

}

SUBIR17,LOW(34)

•Total2bytes

•全局变量

charglobal;

voidmain(void)

{

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++;temp->min++;temp->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/*定义AT90S8515*/

voidmain(void)

{

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”

•选择处理器配置及内存模式

设置C编译器

•设定“intel-extended”为输出格式(releaseonly)

 

设置C编译器

•将文件加入到工程-Project->Files...

 

设置C编译器

•设定“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寄存器在头文件里都被定义为特殊功能寄存器

•象普通变量一样访问

#include/*定义8515*/

voidmain(void)

{

DDRD=0xFF;/*PortD输出*/

}

9.3.1读/写口

#include/*定义AT90S8515*/

voidmain(void)

{

charc;

DDRB=0xFF;/*PortB输出*/

for(;;)/*死循环*/

{

c=PIND;/*读PortD*/

PORTB=c;/*回写到PortB*/

}

}

 

9.3.2延时函数

#include/*定义8515*/

voiddelay(unsignedintdelayValue)

{

unsignedinti;

for(i=0;i

;/*Donothing*/

}

 

9.3.2A:

延时函数

voidmain(void)

{

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*/

#include

#include

voidmain(void)

{

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*/

#include;/*器件配置文件*/

#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;i<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位或一隔一亮灯移位等*/

#include/*预处理命令,头文件*/

#defineBIT(x)(1<<(x))?

*定义位函数,可修改移位方向*/

voiddelay(unsignedchart);/*延时函数*/

{

unsignedchari;

unsignedcharj;

for(i=0;i

for(j=1;j;j++);

}

voidled_pb(unsignedchart);/*LED移位函数*/

{

unsignedchari;

DDRB=0xff;/*设PB口为输出*/

for(i=0;i<8;i++)/*硬件设定低电平灯亮,LED的1位亮灯从B口PB0→PB7*/

{

PORTB=~BIT(i);/*LED亮灯1位*/

delay(t);/*延时*/

}

PORTB=0xff;/*关PB口*/

}

voidled_pd(unsignedchart);/*LED的1位亮灯从D口PD0→PD7移位函数*/

{

unsignedchari;

DDRD=0xff;

for(i=0;i<8;i++)/*LED的1位亮灯从D口PD0→PD7*/

{

PORTD=~BIT(i);

delay(t);

}

PORTD=0xff;

}

voidled_pc(unsignedchart);/*C口PC0→PC7移位函数*/

{

unsignedchari;

DDRC=0xff;

for(i=0;i<8;i++)/*LED的1位亮灯从C口PC0→PDC*/

{

PORTC=~BIT(i);

delay(t);

}

PORTC=0xff;

}

voidled_pa(unsignedchart);/*A口PA7→PA0移位函数*/

{

unsignedchari;

DDRA=0xff;

for(i=8;i>0;i--)/*LED的1位亮灯从A口PA7→PA0*/

{

PORTA=~BIT(i-1);

delay(t);

}

PORTA=0xff;

}

voidmain(void);/*主函数*/

{

unsignedchardt;

while

(1)/*循环*/

{

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函数,改变发音快慢*/

#include/*预处理命令*/

#defineucharunsignedchar

#defineuintunsignedint

voiddelay(uchart)

{

uchari,j;

for(i=0;i

for(j=1;j<150;j++);

}

voidsound_pc0(uchart)

{

uinti;

DDRC=0xff;

PORTC=0xff;

for(i=0;i<350-t*t;i++)/*改变发音快慢,另见SLAVR936B.ASM程序*/

{

PORTC^=(1<<0);

delay(t);

}

}

voidmain(void)/*主函数*/

{

uchardt;

for(;;)

for(dt=1;dt<14;dt++)/*改变发音数量*/

sound_pc0(dt);

}

9.3.78字循环移位显示程序

/*源程序SLAVR937.ASM*/

/*在SL-AVR开发实验器LED数码管上,8字符循环移位显示程序*/

#include/*器件配置文件*/

#defineucharunsignedchar/*定义缩写*/

#defineuintunsignedint

voiddelay(uintt)

{

uinti;

for(i=0;i

}

voidinit_disp(void)/*B口,D口初始化*/

{

DDRB=0xff;

DDRD=0xff;

PORTB=0x7f;/*B口送8字符,字形可修改*/

}

voidscan(void)/*位选扫描*/

{

uchari,j;

for(i=0;i<6;i++)/*i++可修改为一位隔一位或隔2位显示或改变移位方向*/

{

j=150;/*可改变移位速度*/

do

{

PORTD=~(0x01<

delay(150);/*可改变LED显示亮度*/

PORTD=0xff;

delay(2100);/*可改变LED显示亮度*/

}

while(--j);

}

}

voidmain(void)/*主程序*/

{

init_disp();/*初始化*/

for(;;)

scan();/*位选扫描*/

}

 

9.3.8按键加1计数显示程序

/*在SL-AVR开发实验器上,用SHIFT键,按1次键加1计数显示程序*/

#include/*头文件*/

#defineucharunsignedchar/*缩写定义*/

#defineuintunsignedint

flashucharDATA_7SEG[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};/*LED字形表*/

ucharled[6];/*显示缓冲*/

uintcount;/*延时子程序*/

voiddelay(uintt)

{

uinti;

for(i=0;i

}

voidinit_disp(void)/*初始化B口,D口*/

{

DDRB=0xff;

DDRD=0x7f;

PORTD|=0x80;

}

voiddisp(void)/*键盘显示*/

{

uchari;

for(i=0;i<6;i++)

{

PORTD=~(0x01<

PORTB=DATA_7SEG[led[i]];

delay(1000);

}

PORTB=0x00;

PORTD=0xff;

}

voidbe_pc0(void)/*发出一声响子程序*/

{

uinti;

DDRC|=0x01;

for(i=0;i<350;i++)

{

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;

}

voidmain(void)/*主程序*/

{

init_disp();/*初始化B口,D口*/

count=0;/*开始计数值是零*/

conv();/*转换*/

for(;;)

{

while((PIND&0x80)==0x80)/*没有键按下等待*/

disp();/*显示*/

be_pc0();/*发出一声响*/

count++;/*计数器加1*/

conv();/*转换成十进制数*/

while((PIND&0x80)==0)/*有键按下*/

disp();/*显示*/

}

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 法学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1