1、AVR C语言的应用第九章 AVR C语言的应用 更详细资料参阅光盘文件9.1 AVR 支持C和高级语言编程的结构高级语言 提高了MCU的重要性上市的时间简化维护工作轻便学习时间可重用性库 潜在的缺点代码大小执行速度为什么 AVR适宜用高级语言编程?因为它是为高级语言而设计的!IAR对AVR结构和指令集的影响 在结构/指令集确定之前,编译器的开发就开始了 潜在的瓶颈得到确认并消除 IAR的反馈在硬件设计上得到了反映 几次循环反复 修改后的结果从代码当中可看出来Memory system32 通用寄存器数量多直接 与ALU连接可保存变量,指针和之间结果 线性程序存储空间1KBytes - 8MB
2、ytes无需页寻址常数区(SPM可修改) 线性数据存储空间16 MBytes无需页寻址类似于C的寻址模式C 源代码 unsigned char *var1, *var2; *var1+ = *-var2;产生的代码 LD R16,-X ST Z+,R16带偏移量的间接寻址有效访问数组和结构Auto (local variables)放置于软件堆栈之中为适应重入的要求,高级语言都基于堆栈结构四种指针16和32位支持 加法指令加和减寄存器之间寄存器和立即数之间Zero标志的传播 SUB R16,R24 SUBI R16,1 SBC R17,R25 SBCI R17,0所有的跳转都基于最后结果两个1
3、6位数相减Non-destructive comparisonCP R16,R24CPC R17,R25CPC R18,R26CPC R19,R27 带进位比较 Zero传播 无需保存结果 可使用所有形式的跳转Switch 支持 Switches在CASE语句中经常遇到 Straight forward approach 效率低 间接跳转适合于紧凑的switch结构 switch由通用库管理摘 要 AVR结构从一开始就是针对高级语言设计的 Atmel与IAR在结构和指令调整上的合作 从而编译器可以产生高效的代码Efficient C-coding for AVR减少代码的提示和诀窍汇编(Ass
4、embly) 与 C比较汇编: 可以完全控制资源 在小应用当中可以产生紧凑的、高速的代码 在大的应用当中代码效率低 可读性差(Cryptic code) 不好维护 不易移植(Non-portable)C: 对资源的控制有限 在小应中产生的代码量大,执行速度慢 在大的应用当中代码效率高 结构化的代码 容易维护 容易移植访问 I/O 读I/O: temp = PIND; IN R16,LOW(16) 写I/O: TCCR0 = 0x4F; LDI R16,79 OUT LOW(51),R16 I/O的位设置与清除 地址小于0x1F的I/O:PORTB |= (1PIND2);SBI LOW(24)
5、,LOW(2)ADCSR &= (1ADEN);CBI LOW(6),LOW(7) 地址高于0x1F的I/O:TCCR0 &= (0x80);IN R16,LOW(51)ANDI R16,LOW(127)OUT LOW(51),R16测试I/O的单个位 等待地址低于0x1F的单个位的清除while(PIND & (1PIND6);SBIC LOW(16),LOW(6)RJMP ?0002 等待地址高于0x1F的单个位的设置while(!(TIFR & (1sec+; temp-min+; temp-t_count+;带参数的函数调用 使用参数将数据传递到函数中去char add(char nu
6、mber1, char number2)return number1+number2;函数间参数的传递通过R16-R23来实现循 环 死循环for(; ;) 循环char counter = 100;do while(-counter) ;预减变量(Pre-decrement)代码效率最高优化代码的选项 代码大小优化编译 使用局部变量 使用允许的最小数据类型 将全局变量收集到结构中去 死循环使用for(;) 使用预减的do while;C AVR的程序设计程序设计的程序设计内 容 安装必须的工具9.2 C编译的介绍 练习边学边做 用C编程设置编译和链接文件用C访问外围中断处理高级调试 使用不同
7、的AVR外围定时器/计数器UART外部中断Tool flow 器件: AT90S8535 C Compiler AVR studio 仿真 STK200 测试代码 测试程序: 死循环读 Port D的值 (按键,输入口)将其值写到 Port B (LED, 输出口)测试程序#include /* 定义 AT90S8515 */void main(void)char c;DDRB = 0xFF; /* PortB all outputs */ for(;) /* Eternal loop */ c = PIND; /* Read Port D */ PORTB = c; /* 回写到 Port
8、B */ 安装C编译器 Compiler delivered on CD-ROM 安装Dongle驱动器(见“DONGLE.TXT” )设置 C 编译器 启动 IAR Embedded Workbench 可双击快捷图标 创建新工程File - New - Project:设置编译器选项Project - Options设置编译器选项设置链接器文件XLINK设置编译器选项 选择 “Release” 选择处理器配置及内存模式设置 C 编译器设定 “intel-extended” 为输出格式 (release only) 设置 C 编译器将文件加入到工程 - Project - Files .设置
9、 C 编译器 设定 “Debug” 为当前配置 “Make” the program:Project - MakePress F9Toolbutton带调试信息的可执行文件在DEBUGEXE目录使用AVR Studio 启动AVR Studio 加载调试文件 (TestProg.d90) - File - Open 选择AT90S8515 (只需在开始时选择一次) 加入视图(VIEW)I/O (PinB, PortD)ProcessorWatchcPORTBPIND 单步执行, Toggle PIND bits对器件编程选择编程窗口加载Intel-Hex文件(TestProg.hex) - F
10、ile - Load 对器件编程Program - AutoprogramF5Pushbutton9.3 测试应用程序Main函数“main” 是所有C程序的入口点 不要加入参数,也不要返回值 语法: void main(void) /* 代码 */ 访问外围 所有I/O寄存器在头文件里都被定义为特殊功能寄存器 象普通变量一样访问#include /* 定义 8515 */void main(void) DDRD = 0xFF; /* Port D 输出 */9.3.1 读/写口#include /* 定义 AT90S8515 */void main(void)char c;DDRB = 0x
11、FF; /* PortB 输出 */ for(;) /* 死循环 */ c = PIND; /* 读 Port D */ PORTB = c; /* 回写到 Port B */ 9.3.2 延时函数#include /* 定义 8515 */void delay(unsigned int delayValue) unsigned int i; for(i=0;idelayValue;i+) /* 循环 */ ; /* Do nothing */9.3.2A: 延时函数void main(void) unsigned char runner = 0x01; DDRB = 0xff; /* Por
12、t B 输出 */ for (;) /* 死循环 */ if (runner) runner = 1; else runner = 0x01; PORTB = runner; /* 设置 LED */ delay(100); /* 调用延时函数 */ 9.3.3 读/写 E2PROM/* 利用IAR标准I/O函数来读/写 E2PROM */#include #include void main(void)char temp = 0; _EEPUT(0x10,temp); /* 写E2PROM 地址:0x10 */ _EEGET(temp,0x10); /* 读E2PROM 地址: 0x10 *
13、/9.3.4 AVR的PB口变速移位/* 文件名:SLAVR934.ASM */* 位运算符: 按位取反; 右移; 按位与; 按位或; 按位异或;i+相当于i=i+1; i-相当于i=i-1 */#include ; /* 器件配置文件 */#define BIT(x) (1 (x); /* 左移 */void delay(void) unsigned char i,j; for (i=1;i;i+) for(j=1;j;j+); void led_pb(void) unsigned char i; DDRB=0xff; /* 设PB口输出 */ for (i=0;i8;i+) /* 硬件设定
14、低电平灯亮,LED的1位亮灯从B口PB0PB7 */ PORTB=BIT(i); /* LED亮灯1位 */ delay( ); /* 延时 */ void main (void) /* 主函数 */ while (1) /* 循环 */ led_pb( );9.3.5 4个口LED亮灯变速移位/* 文件名:SLAVR935.ASM */* 请修改程序,改变移位方向,2位或3位或一隔一亮灯移位等 */#include /* 预处理命令,头文件 */#define BIT(x) (1 (x) ?* 定义位函数,可修改移位方向 */void delay(unsigned char t) ; /*
15、延时函数 */ unsigned char i; unsigned char j; for (i=0;it;i+) for(j=1;j;j+); void led_pb(unsigned char t) ; /* LED移位函数 */ unsigned char i; DDRB=0xff; /* 设PB口为输出 */ for (i=0;i8;i+) /* 硬件设定低电平灯亮,LED的1位亮灯从B口PB0PB7 */ PORTB=BIT(i); /* LED亮灯1位 */ delay(t); /* 延时 */ PORTB=0xff; /* 关PB口 */void led_pd(unsigned
16、char t) ; /* LED的1位亮灯从D口PD0PD7移位函数 */ unsigned char i; DDRD=0xff; for (i=0;i8;i+) /* LED的1位亮灯从D口PD0PD7 */ PORTD=BIT(i); delay(t); PORTD=0xff; void led_pc(unsigned char t) ; /* C口PC0PC7移位函数 */ unsigned char i; DDRC=0xff; for (i=0;i0;i-) /* LED的1位亮灯从A口PA7PA0 */ PORTA=BIT(i-1); delay(t); PORTA=0xff; vo
17、id main (void) ; /* 主函数 */ unsigned char dt; while (1) /* 循环 */ for (dt=5;dt200;dt+=25) led_pb(dt); /* LED发光二极管一亮灯沿四个口移位变速循环 */ led_pd(dt); led_pc(dt); led_pa(dt); 9.3.6 音符声程序/* 源程序SLAVR936.ASM*/* 可改变t函数,改变发音快慢 */#include /* 预处理命令 */#define uchar unsigned char#define uint unsigned int void delay(uch
18、ar t) uchar i,j; for (i=0;it;i+) for(j=1;j150;j+); void sound_pc0(uchar t) uint i; DDRC=0xff; PORTC=0xff; for (i=0;i350-t*t;i+) /* 改变发音快慢 ,另见SLAVR936B.ASM程序*/ PORTC=(10); delay(t); void main (void) /* 主函数 */ uchar dt; for( ; ; ) for(dt=1;dt14;dt+) /* 改变发音数量 */ sound_pc0(dt);9.3.7 8字循环移位显示程序/* 源程序SLA
19、VR937.ASM*/*在SL-AVR开发实验器LED数码管上,8字符循环移位显示程序*/#include /*器件配置文件*/#define uchar unsigned char /*定义缩写*/#define uint unsigned intvoid delay(uint t) uint i; for (i=0;it;i+); void init_disp(void) /*B口,D口初始化*/ DDRB=0xff; DDRD=0xff; PORTB=0x7f; /*B口送8字符,字形可修改*/void scan(void) /*位选扫描*/ uchar i,j; for (i=0;i6
20、;i+) /*i+可修改为一位隔一位或隔2位显示或改变移位方向*/ j=150; /*可改变移位速度*/ do PORTD=(0x01i); delay(150); /*可改变LED显示亮度*/ PORTD=0xff; delay(2100); /*可改变LED显示亮度*/ while(-j); void main(void) /*主程序*/ init_disp(); /*初始化*/ for( ; ; ) scan( ); /*位选扫描*/ 9.3.8 按键加1计数显示程序/*在SL-AVR开发实验器上,用SHIFT键,按1次键加1计数显示程序*/#include /*头文件*/#define
21、 uchar unsigned char /*缩写定义*/#define uint unsigned intflash uchar DATA_7SEG =0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71;/*LED字形表*/uchar led6; /*显示缓冲*/uint count; /*延时子程序*/void delay(uint t) uint i; for (i=0;it;i+); void init_disp(void) /*初始化B口,D口*/ DDRB=0xff; DD
22、RD=0x7f; PORTD|=0x80;void disp(void) /*键盘显示*/ uchar i; for (i=0;i6;i+) PORTD=(0x01i); PORTB=DATA_7SEGledi; delay(1000); PORTB=0x00; PORTD=0xff; void be_pc0(void) /*发出一声响子程序*/ uint i; DDRC|=0x01; for (i=0;i350;i+) PORTC=0x01; delay(350); void conv(void) /*计数值转换成十进制数*/ led5=0; led4=count/10000; led3=c
23、ount/1000%10; led2=count/100%10; led1=count/10%10; led0=count%10; void main(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