|
发表于 2012-5-25 23:09:53
|
显示全部楼层
下面是我用一个MEGA8+AD420做的一个信号发生器的程序,里面也有用到按键函数部份。
/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.4 Standard
Automatic Program Generator
?Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
Project :
Version :
Date : 2011-6-12
Author :
Company :
Comments:
Chip type : ATmega8L
Program type : Application
Clock frequency : 4.000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 256
*****************************************************/
#include <mega8.h>
#include <delay.h>
#include <lcd.h>
#include <spi.h>
#asm
.equ __lcd_port=0x12 ; PORTD数据寄存器地址
#endasm
#define KEY_MODE 0x08 // 模式按键 PB3
#define KEY_ADD 0x10 // 加 PB4
#define KEY_SUB 0x20 // 减 PB5
unsigned char Trg=0;
unsigned char Cont=0;
char str[10]={'0','1','2','3','4','5','6','7','8','9'};
int dis_buff[6]={0,0,0,0,0,0};
int dis_buff2[6]={0,0,0,0,0,0};
int dis_buff3[6]={0,0,0,0,0,0};
int dis_bufft[3]={0,0,0};
unsigned int Dis_Vale=800;
unsigned char T_vale=0;
unsigned char T_valeb=0;
bit KEY_MODE_ST=1;
unsigned char Dis_outmv_Date=1;
unsigned long BuffDate=0;
unsigned long BuffDate1=0; //N次采样数累加暂存地址空间
bit ZhuanHuanOKBZ=0; //N次采样OK标志值
unsigned char ADC_BZ=0; //ADC转换状态标志
int ZhuanHuanCS=0; //具体采样的次数
unsigned int OKdata=0; //转换OK的输入信号值
unsigned int OKdata1=0; //转换OK的输入信号值
int DateLV=2937; //ADC量程系数5V等于5000 FLUCK表实测Vref 2.937 V
int DateXZ=0;
//手动给定数值显示
void PrintLCD_int(unsigned int adc)
{
char i,ii;
for (i=0;i<=5;i++)
{
dis_buff[i]=adc % 10;
adc /= 10;
}
//换成字符形式方便于LCD显示
for (ii=0;ii<=4;ii++)
{
lcd_gotoxy(ii+10,0); //去LCD第二行第0列显示百位数
lcd_putchar(str[dis_buff[4-ii]]);
}
}
//手动给定值显示函数
void PrintLCD_short(unsigned char ad)
{
char i1;
for (i1=0;i1<=1;i1++)
{
dis_bufft[i1]=ad % 10;
ad /= 10;
}
//换成字符形式方便于LCD显示
lcd_gotoxy(2,0);
lcd_putchar(str[dis_bufft[1]]);
lcd_putchar('.');
lcd_putchar(str[dis_bufft[0]]);
}
//ADC 转换中断服务程序
interrupt[ADC_INT]void adc_m8(void)
{
unsigned int adc_data;
adc_data=ADCW; //读取ADC置换结果
BuffDate1=(unsigned long)adc_data+BuffDate1; //第一步 将过采样数据进行累加
++ZhuanHuanCS;
if(ZhuanHuanCS>=255) //判断N次的采样
{
ZhuanHuanCS=0;
BuffDate=BuffDate1;
BuffDate1=0;
ZhuanHuanOKBZ=1;
ADC_BZ++;
}
}
//第一路输出电流AD采样数据显示
void PrintLCD_intAD0(unsigned int adc)
{
char i;
adc=(unsigned int)(20000/2000)*adc; //2V对应20mA转换函数
for (i=0;i<=4;i++)
{
dis_buff2[i]=adc % 10;
adc/= 10;
}
//换成字符形式方便于LCD显示
lcd_gotoxy(9,1); //去LCD第二行第0列显示百位数
lcd_putchar(str[dis_buff2[4]]);
lcd_putchar(str[dis_buff2[3]]);
lcd_putchar('.');
lcd_putchar(str[dis_buff2[2]]);
lcd_putchar(str[dis_buff2[1]]);
lcd_putchar(str[dis_buff2[0]]);
}
//第二路输出电压AD采样数据显示
void PrintLCD_intAD1(unsigned int adc)
{
char i;
adc=adc*2; //将采样的数据放大2倍。因为硬件上通过放大器将采样信号衰减2倍
for (i=0;i<=3;i++)
{
dis_buff3[i]=adc % 10;
adc /= 10;
}
//换成字符形式方便于LCD显示
lcd_gotoxy(2,1); //去LCD第二行第0列显示百位数
lcd_putchar(str[dis_buff3[3]]);
lcd_putchar('.');
lcd_putchar(str[dis_buff3[2]]);
lcd_putchar(str[dis_buff3[1]]);
lcd_putchar(str[dis_buff3[0]]);
}
//按键扫描处理程序
void KeyProcess(void)
{
//PORTC=0x07;在主程序初始化段设置PC口低三位上拉电阻有效 DDRC=0x00;设置PC口输入模式
unsigned char ReadData=~PINC; //读PC口并将数据取反
Trg=ReadData&(ReadData^Cont); //判断是否点动
Cont=ReadData; //判断是否长按
if(Trg&KEY_MODE)
{
KEY_MODE_ST=~KEY_MODE_ST;
lcd_gotoxy(15,0); //去LCD第二行第0列显示百位数
if(KEY_MODE_ST)
lcd_putchar('+');
else
lcd_putchar('-');
}
if(Trg&KEY_ADD)
{
if(KEY_MODE_ST)
{
if(Dis_Vale<=64223)
{
Dis_Vale=Dis_Vale+1305;
Dis_outmv_Date++ ;
}
}
else
{
if(Dis_Vale>=1312)
{
Dis_Vale=Dis_Vale-1305;
Dis_outmv_Date--;
}
}
}
if(Trg&KEY_SUB)
{
if(KEY_MODE_ST)
{
if(Dis_Vale<=65534)
Dis_Vale=Dis_Vale+2;
}
else
{
if(Dis_Vale>=2)
Dis_Vale=Dis_Vale-2;
}
}
}
//SPI主机初始化函数
void SPI_MasterInitY(void)
{
DDRB=0x2C; //SPI接口SCK PB7设置成输出,SPI接口MOSI PB5设置成输出,SPI接口SS PB4设置成输出。其它设置成输入
PORTB=0x00;
SPCR=0b01010001; //SPI控制寄存器SPCR的第6位SPE设置成1 第4位MAST主从选择设置成1为主方式 第0位为1表示SCK分频系数为什16
}
//SPI主机发送数据函数
void SPI_MasterTransmitY(unsigned char T_Data)
{
SPDR=T_Data; // 向SPI数据寄存器SPDR赋需要传送的值
while(!(SPSR&0x80)) //判断SPI发送数据有没有结束如果结束SPSR状态寄存器的第7位SPIF则为1否则则等待
{};
}
void SPI_TransmitY(unsigned int TrData)
{
unsigned char a,b;
a=TrData/256;
b=TrData%256;
PORTB&=0xFB; //将SPI接口SS PB4置0完成16位数据传
SPI_MasterTransmitY(a); //先传输高8位
SPI_MasterTransmitY(b); //再传输低8位从而组成AD420所需的16位数据
PORTB|=0x04;
}
void main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
PORTB=0x43; //设置PB6,PB1,PB0上拉电阻有效 且为输入模式
DDRB=0x00;
PORTC=0xFC;
DDRC=0x00;
PORTD=0x00;
DDRD=0xFF; //设置PD口为液晶显示器输出接口
// Timer/Counter 0 initialization
TCCR0=0x00;
TCNT0=0x00;
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;
// Analog Comparator initialization
ADMUX=0b00000000;
ADCSRA=0b11101110;
ACSR=0x80;
SFIOR=0x00;
lcd_init(16); //LCD显示器的初始化
SPI_MasterInitY(); //SPI通讯初始化
lcd_gotoxy(15,0);
if(KEY_MODE_ST)
lcd_putchar('+');
else
lcd_putchar('-');
#asm("sei") //开中断
while (1)
{
lcd_gotoxy(0,0);
lcd_putsf("U:"); // display the message
lcd_gotoxy(5,0);
lcd_putsf("00V");
lcd_gotoxy(0,1);
lcd_putsf("o:");
lcd_gotoxy(7,1);
lcd_putsf("V");
lcd_gotoxy(14,1);
lcd_putsf("mA");
if(T_valeb>=20)
{
KeyProcess();
PrintLCD_int(Dis_Vale);
PrintLCD_short(Dis_outmv_Date);
SPI_TransmitY(Dis_Vale);
}
if(T_vale>=25)
{
T_vale=0;
DDRD=DDRD|0b00001000;
PORTD.3=~PORTD.3;
}
T_vale++;
T_valeb++;
if(ZhuanHuanOKBZ)
{
#asm("cli") //开中断
ADCSRA=ADCSRA&0b01111111; //停ADC转换
ZhuanHuanOKBZ=0; //清除标志位
BuffDate=BuffDate/16; //第二步将N次采样的累积数据右移4位
BuffDate=BuffDate*DateLV/16384; //第三步还原14位数据精度的输入值
if(ADC_BZ==1)
{
//AD转换非线性修正
if(BuffDate>=10)
DateXZ=4;
else DateXZ=0;
if(BuffDate>=150)
DateXZ=5;
if(BuffDate>=300)
DateXZ=6;
if(BuffDate>=600)
DateXZ=7;
if(BuffDate>=750)
DateXZ=8;
if(BuffDate>=2100)
DateXZ=9;
if(BuffDate>=2250)
DateXZ=10;
if(BuffDate>=2350)
DateXZ=11;
BuffDate=BuffDate+DateXZ;
OKdata=(unsigned int)BuffDate;
PrintLCD_intAD0(OKdata); //调用adc_to_disbuffer函数将unsigned int数据类型转换成字符形式方便于LCD显示
ADMUX=0b00000001; //采样ADC1
}
if(ADC_BZ==3)
{
//AD转换非线性修正
if(BuffDate>=10)
DateXZ=3;
else DateXZ=0;
if(BuffDate>=60)
DateXZ=4;
if(BuffDate>=250)
DateXZ=6;
if(BuffDate>=700)
DateXZ=7;
if(BuffDate>=1150)
DateXZ=8;
if(BuffDate>=1750)
DateXZ=9;
if(BuffDate>=2150)
DateXZ=10;
if(BuffDate>=2350)
DateXZ=11;
BuffDate=BuffDate+DateXZ;
OKdata1=(unsigned int)BuffDate;
PrintLCD_intAD1(OKdata1); //调用adc_to_disbuffer函数将unsigned int数据类型转换成字符形式方便于LCD显示//调用adc_to_disbuffer函数将unsigned int数据类型转换成字符形式方便于LCD显示
ADMUX=0b00000000; //采样ADC0
}
if(ADC_BZ>=4)
ADC_BZ=0;
ADCSRA=0b11101110; //启动ADC转换
#asm("sei") //开中断
}
};
} |
|