文档库 最新最全的文档下载
当前位置:文档库 › main.c avr128开发板

main.c avr128开发板

/*==================================================本程序需要用到 ===中断==SPI通信== 定时器操作===USART通信=======================
环境: 内部16 M晶振。
AVR mega128学习板

本程序功能=====实现菜单显示: 左键---菜单选择;
右键---数码管位数选择,查看已设置的数值;
上键----数值增加;
下键----数值减少; 数值设定好后保存于Flash中,可供后续查看;

开始:只有--复位---与----左键菜单键------可产生---中断;菜单键按下后 右键方可允许中断; 右键按下后,上下键方可允许中断
===================================================================================================================================*/
#include "iom128v.h"
#include "macros.h"

static unsigned char volatile LED_Menu_dis = 3; //LED选择哪种显示方式,默认为初始化时 显示 -000
static unsigned char volatile Tell_Menu = 0; //区分 各个菜单
static unsigned char volatile Q=0,B=0,S=0,G=0; //四位数
static unsigned char volatile four_one=0;
static unsigned char volatile sd=0; //右键的操作 辨别 闪烁位 和 静态显示
unsigned char Flash_Tell_wei=0;
unsigned char disp[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; /*===========数码管显示码表=====0x8C 数码管显示为 “P”,0x89 数码管显示为 H=======*/
static unsigned char volatile tell_eprom=0;
/*****************************************************函数声明*****************************************/
void IO_init(); //IO初始化

void Int_init(); //中断 初始化

void SPI_Master_init(); //SPI接口 初始化

void LED_P_display(void); //初始时 显示 -000

void LED_menu_Hi_dis(void);//菜单显示

void t1_init(void);

void LED_dis(void); //LED非闪烁显示 ===数值=====Hi===

void LED_Flash(void); //LED动态显示

void LED_Flash_1(void); //一位数码管按指令闪烁

void LED_Flash_4(void); //四位数码管按指令闪烁

void eprom_read(unsigned int addr,unsigned char volatile*buff); /*EEPROM读取函数addr:地址;number:长度;p_buff:读出数据存放指针*/

void eprom_write(unsigned int addr,unsigned char volatile*buff); /*EEPROM写入函数addr:地址;number:长度;p_buff:写入数据存放指针*/


void main( void )
{
IO_init();
Int_init(); //此函数中 只开复位 和 左键 中断
SPI_Master_init() ; //SPI接口 初始化
while(1)
{
if(LED_Menu_dis==0)

LED_menu_Hi_dis(); //显示菜单

else if(LED_Menu_dis==1)

LED_dis(); //LED静态显示: 数值----one_or_three取值:

1--显示1位数值;3--显示3位数值

else if(LED_Menu_dis==2)

LED_Flash(); //LED动态显示

else

LED_P_display(); //初始时 显示 -000
}
}

/******************************************************************************初始化函数定义*****************************************************************/

void IO_init() //IO初始化
{
DDRA = 0x00; /*方向输入*/
PORTA = 0xFF; /*打开上拉*/

DDRB = 0xF4; /*0b 1111---0100==========设置4-7位为输出,控制4位数码管;2--MOSI为输出 */
PORTB = 0xFB; /*0b 0000---1011=========4-7位输出低电平,点亮4位数码管*/

DDRC = 0x00; /*不用的IO口建议设置为输入带上拉*/
PORTC = 0xFF;

DDRD = 0x00;
PORTD = 0xFF;

DDRE = 0x00; // 0b 1111---0000中断引脚 配置为输入 只用 引脚 0 , 1
PORTE = 0xFF; // 0b 0000---1111中断引脚 配置为输入 只用 引脚 0 , 1

DDRF = 0x00;
PORTF = 0xFF;
DDRG = 0x00;
PORTG = 0xFF;
}

void Int_init() //中断 初始化
{
CLI(); /*关全局中断*/
EIMSK = 0x00; /*屏蔽所有外部中断*/
EICRA = 0x00;
EICRB = 0xAA; /*INT4-INT7设置为低电平触发*/
EIFR = 0xFF; /*清除中断标志,请见中文手册P84*/
EIMSK = 0x10; /*0b 0001--0000 INT4允许-INT5--7先禁止*/
SEI(); /*全局中断允许*/
}

void SPI_Master_init() //SPI接口 初始化
{
DDRB |= (1<SPCR = (1<}

void t1_init(void)
{
TCNT1=0x0000;
OCR1A = 65535; /*计数周期为10mS,F=1M OCR1A=1250 改为-----F=16M时,OCR1A =31250, 计数周期0.5s*/
TIMSK |= (1 << OCIE1A); /*比较中断A允许*/
TCCR1A = 0x00;
TCCR1B = (1 << WGM12); /*定时器工作在CTC计数器模式*/
TCCR1B |= 0x05; /*设置定时器的分频值为1024分频*/
}

/******************************************************************************初始化函数定义结束**************************************************************/
/*************************************************eeprom操作函数定义*****************************************/

/*EEPROM读取函数*/
/*addr:地址;number:长度;p_buff:读出数据存放指针*/
void eprom_read(unsigned int addr,unsigned char volatile*buff) {

while(EECR & (1 << EEWE)); /* 等待上一次写操作结束 */

EEAR = addr; /* 设置地址寄存器 */
EECR |= (1 << EERE); /* 置位EERE 读使能 */
*buff = EEDR;
}

/*EEPROM写入函数*/
/*addr:地址;number:长度;p_buff:写入数据存放指针*/
void eprom_write(

unsigned int addr,unsigned char volatile *buff) {
CLI(); //防止写操作时有中断 产生写误差
while(EECR & (1 << EEWE)); /* 等待上一次写操作结束 */
EEAR = addr; /* 设置地址寄存器 */
EEDR = *buff; /* 设置数据寄存器 */
EECR |= (1 << EEMWE); /* 置位EEMWE 主机写使能*/
EECR |= (1 << EEWE); /* 置位EEWE 写使能*/
SEI();
}

/**************************************************************eeprom函数定义结束******************************/
/******************************************************显示函数定义********************************************/
void delay_ms(unsigned char i)
{
unsigned char a, b;
for (a = 0; a < i; a++) {
for (b = 1; b; b++);
}
}
void SPI_MasterTransmit(unsigned char i) //SPI传输数据 让 LED 显示
{
SPDR = i; /* 启动数据传输 */
while (!(SPSR & (1<}

void LED_P_display() //初始时 显示 -000
{
static unsigned int i=100 ;
i--;
PORTB = 0xEE; /*个位 准备锁存*/
SPI_MasterTransmit(disp[0]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(100);

PORTB = 0xDE; /*十位 准备锁存*/
SPI_MasterTransmit(disp[0]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(100);

PORTB = 0xBE; /*百位 准备锁存*/
SPI_MasterTransmit(disp[0]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(100);

if(i>50)
{
PORTB = 0xFF;
}
else if(i==0)i=100;
else
{ PORTB = 0x7E; /*-------------+++++"-"号++++-------闪烁---------*/
SPI_MasterTransmit(0xBF);
PORTB |= (1 << PB0);
delay_ms(50);
}
}

void LED_menu_Hi_dis()//菜单显示
{
PORTB = 0xDE; /*个位 准备锁存*/
SPI_MasterTransmit(disp[Tell_Menu]);
PORTB |= (1 << PB0); /*锁存数据*/

PORTB = 0xEE; /*十位 准备锁存*/
SPI_MasterTransmit(0x89); /*------0x89----H------*/
PORTB |= (1 << PB0); /*锁存数据*/
}

void LED_dis(void) //LED非闪烁显示 ===数值=====Hi===
{
switch(four_one)
{
case 4: PORTB = 0xEE; /*个位 准备锁存*/
SPI_MasterTransmit(disp[G]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(60);

PORTB = 0xDE; /*十位 准备锁存*/
SPI_MasterTransmit(disp[S]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(60);

PORTB = 0xBE; /*百位 准备锁存*/
SPI_MasterTransmit(disp[B]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(60);

PORTB = 0x7E; /*千位 准备锁存*/
SPI_MasterTransmit(disp[Q]);
PORTB |= (1

<< PB0); /*锁存数据*/
delay_ms(60);
break;

case 1: PORTB = 0xEE; /*个位 准备锁存*/
SPI_MasterTransmit(disp[G]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(60);
break;
default: break;
}
}

void LED_Flash(void) //LED动态显示
{
switch(four_one)
{
case 1: LED_Flash_1();
break;

case 4: LED_Flash_4(); //四位数码管按指令闪烁
break;
}
}
void LED_Flash_1()
{
unsigned static int i=200;
i--;
unsigned char temp;
temp = sd;
temp--;
if(temp==1)
{
if(i>100)
{
PORTB = 0xEE; /*个位 准备锁存*/
SPI_MasterTransmit(disp[G]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(100);
}
else if(i==0)i=200;
else
{
PORTB = 0xFE; //关闭四个数码管
delay_ms(100);
}
}
}
void LED_Flash_4() //四位数码管按指令闪烁
{
unsigned char temp;
temp = sd;
temp--;
unsigned static int i=90;
i--;
switch(temp)
{
case 1: if(i>45)
{
PORTB = 0xEE; /*个位 准备锁存*/
SPI_MasterTransmit(disp[G]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(50);
}
else if(i==0)i=90;
else
{
PORTB = 0xFE;
delay_ms(50);
}

PORTB = 0xDE; /*十位 准备锁存*/
SPI_MasterTransmit(disp[S]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(60);

PORTB = 0xBE; /*百位 准备锁存*/
SPI_MasterTransmit(disp[B]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(60);

PORTB = 0x7E; /*千位 准备锁存*/
SPI_MasterTransmit(disp[Q]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(60);
break;

case 2: PORTB = 0xEE; /*个位 准备锁存*/
SPI_MasterTransmit(disp[G]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(60);

if(i>45)
{
PORTB = 0xDE; /*十位 准备锁存*/
SPI_MasterTransmit(disp[S]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(50);
}
else if(i==0)i=90;
else
{

PORTB = 0xFE;
delay_ms(50);
}

PORTB = 0xBE; /*百位 准备锁存*/
SPI_MasterTransmit(disp[B]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(60);

PORTB = 0x7E; /*千位 准备锁存*/
SPI_MasterTransmit(disp[Q]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(60);
break;

case 3: PORTB = 0xEE; /*个位 准备锁存*/
SPI_MasterTransmit(disp[G]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(60);

PORTB = 0xDE; /*十位 准备锁存*/
SPI_MasterTransmit(disp[S]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(60);

if(i>45)
{
PORTB = 0xBE; /*百位 准备锁存*/
SPI_MasterTransmit(disp[B]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(50);
}
else if(i==0)i=90;
else
{
PORTB = 0xFE;
delay_ms(50);
}

PORTB = 0x7E; /*千位 准备锁存*/
SPI_MasterTransmit(disp[Q]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(60);
break;

case 4: PORTB = 0xEE; /*个位 准备锁存*/
SPI_MasterTransmit(disp[G]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(60);

PORTB = 0xDE; /*十位 准备锁存*/
SPI_MasterTransmit(disp[S]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(60);

PORTB = 0xBE; /*百位 准备锁存*/
SPI_MasterTransmit(disp[B]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(60);

if(i>45)
{
PORTB = 0x7E; /*千位 准备锁存*/
SPI_MasterTransmit(disp[Q]);
PORTB |= (1 << PB0); /*锁存数据*/
delay_ms(50);
}
else if(i==0)i=90;
else
{
PORTB = 0xFE;
delay_ms(50);
}
break;
default: break;
}
}
/*******************************************************显示函数定义结束****************************************/
/**********************************************************************************中断函数**************************************************************/
#pragma vector=0x14 //左键中断 (INT4) 菜单显示
__interrupt void EXT_Menu(void)
{
unsigned int i=2000;

/*防按键颤动代码*/
while (i --)
{
if ((PINE & (1 << PE4)) != 0) //S0按键是否为低电平
return ;
}

LED_Menu_dis =0;

Tell_Menu++;
if(Tell_Menu==6)
Tell_Menu=6;
else
Tell_Menu=Tell_Menu%6;

sd=0;
EIMSK |=0x20; //开右键中断(INT5)
}

#pragma vector=0x18 //右键中断 (INT5)
__interrupt void EXT_slect_wei(void)
{
unsigned int i=2000;

/*防按键颤动代码*/
while (i --)
{
if ((PINE & (1 << PE5)) != 0) //S0按键是否为低电平*/
return ;
}
tell_eprom=0;
TCCR1B &=0xF8;//关闭时钟
if(sd==0)
{
LED_Menu_dis=1; /*静态显示*/
//从flash中读取数据
switch(Tell_Menu)
{
case 1:eprom_read(0x00,&G);eprom_read(0x01,&S);eprom_read(0x02,&B);eprom_read(0x03,&Q); four_one = 4; break;
case 2:eprom_read(0x04,&G);eprom_read(0x05,&S);eprom_read(0x06,&B);eprom_read(0x07,&Q); four_one = 4; break;
case 3:eprom_read(0x08,&G);eprom_read(0x09,&S);eprom_read(0x0A,&B);eprom_read(0x0B,&Q); four_one = 4; break;
case 4:eprom_read(0x0C,&G); four_one = 1; break;
case 5:eprom_read(0x0D,&G); four_one = 1; break;
case 6:eprom_read(0x0E,&G); four_one = 1; break;
default: break;
}
if(four_one==4){if(G>9)G %=9;if(S>9)S %=9;if(B>9)B %=9;if(Q>9)Q %=9;}
if((four_one==1)&&((Tell_Menu==4)||(Tell_Menu==5))){if(G>1)G %=2;}
if((four_one==1)&&(Tell_Menu==6))if(G>4)G=G%5;
}
else
{ EIMSK |=0xC0; //开上下键中断
LED_Menu_dis=2; //动态显示
switch(Tell_Menu) //选择闪烁位
{
case 1:
case 2:
case 3: break;
case 4:
case 5:
case 6: sd=1; break;
default: break;
}
}
sd++;
if(sd>=6)sd=2;
t1_init();//开启时间计数器 在产生的中断中 屏蔽右、下、上中断,写eeprom TCCR1B &= 0xF8----设为无时钟源即关闭时钟计数器;
}

#pragma vector=0x1C //上键中断 (INT6)
__interrupt void EXT_Up_number(void)
{
unsigned int i=2000;
unsigned char temp=0;

/*防按键颤动代码*/
while (i --)
{
if ((PINE & (1 << PE6)) != 0) //S0按键是否为低电平*/
return ;
}

TCCR1B &= 0xF8;//关闭时钟
temp=sd;
temp--;
tell_eprom=1;
switch(Tell_Menu)
{
case 1:
case 2:
case 3: if(temp==1){++G;if(G>9)G=0;}
else if(temp==2){++S;if(S>9)S=0;}
else if(temp==3){++B;if(B>9)B=0;}
else if(temp==4){++Q;if(Q>9)Q=0;}
break;
case 4:
case 5:G^=0x01; break;
case 6:G++;if(G>4)G=0;
default: break;
}
t1_init();
}

#pragma vector=0x20 //下键中断 (INT7)
__interrupt void EXT_De_number(void)
{
unsigned int i=2000;
unsigned char temp=0;

/*防按键颤动代码*/
while (i --

)
{
if ((PINE & (1 << PE7)) != 0){ //S0按键是否为低电平*/
return ;
}
}

TCCR1B &= 0xF8;//关闭时钟
temp=sd;
temp--;
tell_eprom=1;
switch(Tell_Menu)
{
case 1:
case 2:
case 3:if(temp==1){ if(G==0)G=9;else G--;}if(temp==2){if(S==0)S=9;else S--;}if(temp==3){if(B==0)B=9;else B--;}if(temp==4){if(Q==0)Q=9;else Q--;}
break;
case 4:
case 5:G^=0x01; break;
case 6:if(G==0)G=4;else G--;
default: break;
}
t1_init();
}

/*定时器T1 TCCR1A组比较匹配中断-----------------两个功能:1--闪烁显示时 计时 让闪烁位闪烁 2----全部停止闪烁 回到菜单选择,此时屏蔽 右、下、上、中断*/
#pragma vector =0x30
__interrupt void T1_Int(void)
{
EIMSK &=0x10;
TCCR1B &= 0xF8;//设为无时钟源即关闭时钟计数器
LED_Menu_dis=3;//返回菜单
//写EEPROM
if(tell_eprom)
{
switch(Tell_Menu)
{
case 1:eprom_write(0x00,&G);eprom_write(0x01,&S);eprom_write(0x02,&B);eprom_write(0x03,&Q); break;
case 2:eprom_write(0x04,&G);eprom_write(0x05,&S);eprom_write(0x06,&B);eprom_write(0x07,&Q); break;
case 3:eprom_write(0x08,&G);eprom_write(0x09,&S);eprom_write(0x0A,&B);eprom_write(0x0B,&Q); break;
case 4:eprom_write(0x0C,&G); break;
case 5:eprom_write(0x0D,&G); break;
case 6:eprom_write(0x0E,&G); break;
default: break;
}
}
Tell_Menu = 0;
}
/*****************************************************************************************中断函数结束************************************************/

相关文档