史上最全的AVR128例程.docx
《史上最全的AVR128例程.docx》由会员分享,可在线阅读,更多相关《史上最全的AVR128例程.docx(45页珍藏版)》请在冰豆网上搜索。
史上最全的AVR128例程
自己学avr单片机已经有相当一段时间了,一开始用的是atmega128,觉得不是很好用。
于是自己去买了一块16L的芯片,觉得还行。
一开始用的是ICCAVR,应为它用起来比较简单,不像winavr那样,要写个Makefie
,比较的麻烦,但iccavr的缺点是太过于简陋,调试程序时,感觉不是很好。
后来经同学介绍,用起了winavr,其实也是比较的简单,只不过要加一个makefile而已,其实makefile可以用软件自带的组建自动生成,只需修改几个参数就可以用。
后来又用起了codevisionavr,虽然不太习惯,也谈不上不好用.
需要注意的是,三个不同的软件所带的同文件不一样。
iccavr是iom128v.h(姑且以128为例),winavr是avr/io.h,不过makefile中要设置芯片为atmega128.而cvavr则是mega128.h。
记得一开始的时候,我对这些不同的同文件不是很理解,是从一个学长那里了解到,才弄明白的。
其实前两个软件只需把头文件稍微改一下基本上可以通用。
而最后一个软件的中断的写法似乎不太一样,因而和钱两个软件的兼容性是最差的。
总体说winavr给人的感觉是比较专业
1、流水灯
/*
硬件环境:
atmega128开发板
软件环境:
CodeVisionAVR-C
*/
#include
#define ucharunsignedchar
#define uint unsignedint
ucharcnt;
voidtimer1_init()
{
TCCR1B=0X00; //先停止定时器1
TCNT1H=0XF0; //设定定时器初值
TCNT1L=0XBE;
TCCR1A=0X00; //启动定时器1
TCCR1B=0X05; //使用1024分频
}
interrupt[TIM1_OVF]voidtimer1_ovf_isr(void)
{
TCNT1H=0XF0; //重载定时器初值
TCNT1L=0XBE;
DDRE|=1<<2;
PORTE|=1<<2;
DDRA=0xff;
PORTA=cnt; //输出led的值到端口B
cnt++;
if(cnt==255)
cnt=0;
}
voidmain()
{
//DDRB=0XFF;
SREG|=0X80;
TIMSK=0X04;
timer1_init();
while
(1)
{;
}
}
2、AD转换+数码管显示
/***************************************************************************/
/*ADC测试程序 */
/*目标器件:
ATmega128 */
/*晶振:
RC8MHZ */
/*编译环境:
ICCAVR7.13A */
/*E-Mail:
number007cool@ */
/*时间:
2010年11月13日 */
//Aref接AVCC(+5V),采用Aref作参考电压
/*用数码管显示AD转换的结果*/
/***************************************************************************/
/*********************************包含头文件********************************/
#include
#include
/********************************数码管段码表*******************************/
externconstunsignedchartab[]={0x3f,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
0x7F,0x6F};
/*********************************全局变量**********************************/
unsignedintadc_rel=0;
/****************************************************************************
函数功能:
ADC初始化函数
入口参数:
出口参数:
****************************************************************************/
voidadc_init(void)
{
DDRF&=0XFE; //PORTF0设置为输入,即作为ADC0口输入模拟电压
PORTF&=0XFE; //PORTF0设置为输入低电平
ADCSRA=0x00; //关ADC
ADMUX=0X00; //采用Aref作为参考电压,ADC0单端输入,右对齐
ACSR=(1<ADCSRA=(1<//ADEN,启动ADC;ADSC,ADC开始转换;ADIE,ADC中断使能;ADPSx,设置分频因子64
}
/****************************************************************************
函数功能:
ADC中断函数
入口参数:
出口参数:
****************************************************************************/
#pragmainterrupt_handleradc_isr:
iv_ADC
voidadc_isr(void)
{
//intdata_h,data_l;
//data_l=ADCL;
//data_h=ADCH;
ADCSRA=0x00;
ADCSRA=(1< adc_rel=ADC;
/*
if(adc_rel>0x1ff)
{
PORTA|=1<<2;
}
else
PORTA&=~(1<<2);
*/
}
/****************************************************************************
函数功能:
延时子程序
入口参数:
出口参数:
****************************************************************************/
voiddelay(void)
{
inti;
for(i=0;i<1800;i++);
}
/****************************************************************************
函数功能:
显示子程序
入口参数:
k
出口参数:
****************************************************************************/
voiddisplay(unsignedintk)//发光二极管显示初始化
{
DDRE|=1<<2;
PORTE|=1<<2;
DDRA=0XFF;
PORTA=k;
}
#defineSS0
#defineSCK1
#defineMOSI2
#defineMISO3
#defineSS_H()PORTB|=(1<#defineSS_L()PORTB&=~(1<#defineled0_en() {DDRB|=1<<4;PORTB|=(1<<4);} //开第一个数码管的位选
#defineled0_dis() {DDRB|=1<<4;PORTB&=~(1<<4);} //关第一个数码管的位选
#defineled1_en() {DDRB|=1<<5;PORTB|=(1<<5);}
#defineled1_dis() {DDRB|=1<<5;PORTB&=~(1<<5);}
#defineled2_en() {DDRB|=1<<6;PORTB|=(1<<6);}
#defineled2_dis() {DDRB|=1<<6;PORTB&=~(1<<6);}
#defineled3_en() {DDRB|=1<<7;PORTB|=(1<<7);}
#defineled3_dis() {DDRB|=1<<7;PORTB&=~(1<<7);}
#defineOE7
#definepoint 3
#definedp 7
#include
#include
constunsignedchartable[]={0x3F,0x06,0x5B,0x4F,0x66, //0,1,2,3,4
0x6D,0x7D,0x07,0x7F,0x6F, //5,6,7,8,9
0x77,0x7C,0x39,0x5E,0x79,0x71,0x00}; //a,b,c,d,e,f
volatileunsignedcharled_buffer[4];
voiddelay_1us(void) //1us延时函数
{
asm("nop");
}
voiddelay_nus(unsignedintn) //Nus延时函数
{
unsignedinti=0;
for(i=0;i delay_1us();
}
voiddelay_1ms(void) //1ms延时函数
{
unsignedinti;
for(i=0;i<1140;i++);
}
voiddelay_nms(unsignedintn) //Nms延时函数
{
unsignedinti=0;
for(i=0;i delay_1ms();
}
/*完成spi的初始化*/
voidspi_init(void)
{
DDRB|=(1< SPCR=(1<}
/*spi主机传送数据*/
voidSPI_MasterTransmit(charData)
{
/*启动数据传输*/
SPDR=Data;
/*等待传输结束*/
while(!
(SPSR&(1< ;
}
/*完成对HC595的初始化*/
voidHC_595_init(void)
{
DDRC|=(1< PORTC&=(1< PORTB=0x0F; //同时打开四个数码管的位选
spi_init();
led_buffer[0]=16; //初始化数码管段码
led_buffer[1]=16;
led_buffer[2]=16;
led_buffer[3]=16;
}
/*HC595完成传送数据*/
voidHC_595_OUT(unsignedchardata)
{
SS_L();
SPI_MasterTransmit(data);
SS_H();
}
voidleddis_update(void)
{
/*最低位数码管,第四个数码管*/
if(point==0)
HC_595_OUT(table[led_buffer[3]]|(1< else
HC_595_OUT(table[led_buffer[3]]);
led0_en();
delay_nus(60);
led0_dis();
if(point==1)
HC_595_OUT(table[led_buffer[2]]|(1< else
HC_595_OUT(table[led_buffer[2]]);
led1_en();
delay_nus(60);
led1_dis();
if(point==2)
HC_595_OUT(table[led_buffer[1]]|(1< else
HC_595_OUT(table[led_buffer[1]]);
led2_en();
delay_nus(60);
led2_dis();
/*最高位数码管,第一个数码管*/
if(point==3)
HC_595_OUT(table[led_buffer[0]]|(1< else
HC_595_OUT(table[led_buffer[0]]);
led3_en();
delay_nus(60);
led3_dis();
}
voiddisplay_led(unsignedintdata)
{
if(data>9999)
{
HC_595_OUT(0xFF);//当计数大于9999时,四个数码管同时输出8
PORTB|=((1<<4)|(1<<5)|(1<<6)|(1<<7));
}
elseif(data>999)
{
led_buffer[0]=data/1000;
led_buffer[1]=(data%1000)/100;
led_buffer[2]=(data%100)/10;
led_buffer[3]=data%10;
leddis_update();
}
elseif(data>99)
{
led_buffer[0]=data/1000; //关闭最高位的那个数码管
led_buffer[1]=(data%1000)/100;
led_buffer[2]=(data%100)/10;
led_buffer[3]=data%10;
leddis_update();
}
elseif(data>9)
{
led_buffer[0]=data/1000;
led_buffer[1]=16;
led_buffer[2]=(data%100)/10;
led_buffer[3]=data%10;
leddis_update();
}
else
{
led_buffer[0]=data/1000;
led_buffer[1]=16;
led_buffer[2]=16;
led_buffer[3]=data%10;
leddis_update();
}
}
volatileunsignedintcountnum=0;
voidtimer1_init(void)
{
TCCR1B=0x00;//stop
TCNT1H=0x8F;//setup
TCNT1L=0x81;
OCR1AH=0x70;
OCR1AL=0x7F;
OCR1BH=0x70;
OCR1BL=0x7F;
OCR1CH=0x70;
OCR1CL=0x7F;
ICR1H =0x70;
ICR1L =0x7F;
TCCR1A=0x00;
TCCR1B=0x04;//startTimer
}
#pragmainterrupt_handlertimer1_ovf_isr:
15
voidtimer1_ovf_isr(void)
{
TCNT1H=0x8F;//reloadcounterhighvalue
TCNT1L=0x81;//reloadcounterlowvalue
countnum++;
if(countnum>9999)countnum=0;
}
voidinit_devices(void)
{
CLI();//disableallinterrupts
timer1_init();
TIMSK=0x04;//timerinterruptsources
SEI();//re-enableinterrupts
}
/****************************************************************************
函数功能:
主程序
入口参数:
出口参数:
****************************************************************************/
voidmain(void)
{
init_devices();
HC_595_init();
adc_init();
SEI();//开全局中断变量
display(0);
while
(1)
{
delay();
display_led(adc_rel/1024.0*5*1000);
}
}
3、对EEPROM进行读写操作
/************************************************
文件:
main.c
用途:
注意:
内部8M晶振
************************************************/
#include"config.h"
/*向EEPROM里面写入数据
输入量:
地址,数据*/
voidEEPROM_write(unsignedintuiAddress,unsignedcharucData)
{
while(EECR&(1< EEAR=uiAddress; //地址
EEDR=ucData; //数据
EECR|=(1< EECR|=(1<}
/*从EEPROM指定的地址里面读出相应的数据*/
unsignedcharEEPROM_read(unsignedintuiAddress)
{
while(EECR&(1< EEAR=uiAddress; //设置地址寄存器
EECR|=(1< returnEEDR; //返回读入EEDR里面的数据
}
voidmain(void)
{
unsignedchartemp=123;
unsignedchardata;
HC_595_init();
EEPROM_write(0x01,temp);
data=EEPROM_read(0x01);
while
(1)
{
Seg7_Led_display(data); //调用显示函数将写入的数据又读出来
}
}
文件:
eeprom12.rar
大小:
40KB
下载:
下载
4、定时器0(轮循方式)
/*定时器0和2(均为八位的定时计数器)有四种工作模式,此例是工作在普通模式。
在此模式下,计数器不断的累加,当计数到最大值0xff后返回到0x00重新开始,在TCNT0
为0的同时,T/C溢出标志TOV0置位*/
//使用轮循方式,当TIFR溢出时,uc_led加1,输出到led时期发光
//TIFR中断标志寄存器
#include
#defineucharunsignedchar
ucharuc_led,k;
voidmain()
{
//设置数码管输出高电平
DDRE|=1<<2;
PORTE|=1<<2;
DDRA=0XFF;
PORTF=0XFF;
TCNT0=0X00;//设定定时计数器的初值为0
TCCR0=0X05;//使用1024分频(共有7种时钟)
uc_led=0;
k=0;
while
(1)
{
while(!
(TIFR&0X01));//循环检测TIFR中的溢出标志是否有效
//PORTA=uc_led;
uc_led++;
if(uc_led==255)
{uc_led=0;
k++;
if(k==255)
k=0;
PORTA=k;
}
TIFR|=0X01;//写1到TIFR的TOV0位清除溢出标志为TOV0
}
}
5、定时器0中中