////////////////////////////////////////////////////////////////////////////////
////环境:编译为ICCAVR 6.25A
////单片机:ATMEGA 8A
////日期:2014年2月11日
////功能:CD纹机控制器
////作者:夜猫子(QQ610027265)
////晶振:外部有源晶振,主频10M
////备注:适合用于 恒源隆的CD纹机的自动控制
////////////////////////////////////////////////////////////////////////////////
//包含头文件////////////////////////////////////////////////////////////////////
#include<iom16v.h>
#include<macros.h>
//定义数据类型//////////////////////////////////////////////////////////////////
#define uchar unsigned char
#define uint unsigned int
//定义输出io口//////////////////////////////////////////////////////////////////
#define Y1_OUT DDRC|=BIT(5);
#define Y1_H PORTC|=BIT(5);
#define Y1_L PORTC&=~BIT(5);
#define Y2_OUT DDRD|=BIT(6);
#define Y2_H PORTD|=BIT(6);
#define Y2_L PORTD&=~BIT(6);
#define Y3_OUT DDRD|=BIT(7);
#define Y3_H PORTD|=BIT(7);
#define Y3_L PORTD&=~BIT(7);
#define Y4_OUT DDRB|=BIT(0);
#define Y4_H PORTB|=BIT(0);
#define Y4_L PORTB&=~BIT(0);
#define Y5_OUT DDRC|=BIT(4);
#define Y5_H PORTC|=BIT(4);
#define Y5_L PORTC&=~BIT(4);
#define Y6_OUT DDRB|=BIT(1);
#define Y6_H PORTB|=BIT(1);
#define Y6_L PORTB&=~BIT(1);
//ad求平均的个数(N的值越大ad越准)///////////////////////////////////////////////
#define N 3
//数码管亮度调节0x00-0xff
#define P 0x01
//定时器的初值//////////////////////////////////////////////////////////////////
#define TEMERH 0xf0
#define TEMERL 0x00
//全局变量//////////////////////////////////////////////////////////////////////
uint addata,adc,i,q=1,t1,t2,t3,tt1,tt2,tt3;
uchar g1,g2,g3;
//io初始化//////////////////////////////////////////////////////////////////////
void port_init()
{
DDRC&=BIT(0)&BIT(1)&BIT(2)&BIT(3); //AD转换口设置为输入
PORTC&=BIT(0)&BIT(1)&BIT(2)&BIT(3); //AD转换口设置为无上拉
DDRD|=0x3f;
PORTD|=0x3f; //配置PD口为输入,有上拉电阻
DDRD&=0xC0;
Y1_H;Y2_H;Y3_H;Y4_H;Y5_H;Y6_H; //输出为高电平
Y1_OUT;Y2_OUT;Y3_OUT;Y4_OUT;Y5_OUT;Y6_OUT; //配置成输出
}
//spi初始化/////////////////////////////////////////////////////////////////////
void spi_init()
{
DDRB|=BIT(2)|BIT(3)|BIT(5);//置spi数据口为输出
SPCR=0x51;
PORTB|=BIT(2);
SPSR&=0x7f;
}
//初始化max7219数码管模块////////////////////////////////////////////////////////
void initmax7219()
{
spi_init();
max7219(0x0c,0x00); //掉电模式:0,普通模式:1
max7219(0x09,0xff); //译码方式:BCD码
max7219(0x0a,P); //亮度调节
max7219(0x0b,0x07); //扫描界限;4个数码管显示
max7219(0x0c,0x01); //掉电模式:0,普通模式:1
max7219(0x0f,0x00); //显示测试:1;测试结束,正常显示:0
max7219(3,10); max7219(6,10); //显示横杠
delay_ms(2);
}
//定时器1初始化子程序///////////////////////////////////////////////////////////
void init_timer1()
{
TCCR1B|=0x04;//256分频
TCNT1H=TEMERH;//高8位初值
TCNT1L=TEMERL;//低8位初值
TIMSK|=BIT(2);//定时器1的中断使能
}
//延时函数//////////////////////////////////////////////////////////////////////
void delay_ms(uint i)
{
while(i--)
{
uint j;
for(j=1;j<=1332;j++);
}
}
//向max7219写入地址和数据///////////////////////////////////////////////////////
void max7219(uchar add,uchar date)
{
PORTB&=~BIT(2);
SPDR=add;
while(!(SPSR&0x80));
add=SPSR;//读取SPSR来清除SPIF;
SPDR=date;
while(!(SPSR&0x80))
date=SPSR;
PORTB|=BIT(2);
}
//ADC单次转换子程序带1个参数,1个返回值/////////////////////////////////////////
int Mega8_ad(uchar chl)
{
uint sum=0;
uchar count;
ADMUX=0x00; //采用外部参考电压,输出数据右对齐
ADMUX|=chl; //设置指定的通道
ADCSR=0x80; //使能adc采用单次转换,查询模式,
ADCSR|=BIT(1)|BIT(0); //8分频
for(count=0;count<N;count++)
{
ADCSR|=BIT(6); //启动转换
while(!(ADCSR&(BIT(ADIF)))); //等待转换结束
addata=ADCL; //读取低8位数据
addata+=ADCH*256; //读取高2位数据
adc=addata/10.24;
sum=sum+adc;
delay_ms(1);
}
return (sum/N); //返回N次转换的平均值
}
//切换ADC通道采集四个电位器的值送液晶显示//////////////////////////////////////
void adc_max7219()
{
uchar shi1=0, ge1=0;
t3=Mega8_ad(0X40); //选择PC0为AD通道,将转换结果赋给t1
max7219(2,t3/10);
max7219(1,t3%10); //送显示
delay_ms(2);
t2=Mega8_ad(0X41); //选择PC1为AD通道,将转换结果赋给t1
max7219(5,t2/10);
max7219(4,t2%10); //送显示
delay_ms(2);
t1=Mega8_ad(0X43); //选择PC3为AD通道,将转换结果赋给t1
max7219(8,t1/10);
max7219(7,t1%10 ); //送显示
delay_ms(2);
}
//////看门狗初始化//////////////////////////////////////////////////////////////
void watchdog_init(void)
{
WDR(); //this prevents a timout on enabling
WDTCR = 0x1F; //特别注意这一条不是ICC生成的,是后来加上的。
WDTCR = 0x0c; //WATCHDOG ENABLED - dont forget to issue WDRs
}
//主函数////////////////////////////////////////////////////////////////////////
void main()
{
watchdog_init();//看门狗
port_init(); //初始化io
initmax7219(); //初始化max7219
Mega8_ad(0X40); //启动一次通道0的AD转换 此值舍去
Mega8_ad(0X41); //启动一次通道1的AD转换 此值舍去
Mega8_ad(0X43); //启动一次通道3的AD转换 此值舍去
adc_max7219(); //启动一次通道0123的AD转换 送显示
init_timer1(); //初始化定时器1
SREG|=BIT(7); //打开总中断
while(1) //循环//这里面主要检测按键
{
WDR();
///////////////////////////////////////////////////////////////////////////////
if(!(PIND&BIT(2)))//停止按钮
{
delay_ms(5);
if(!(PIND&BIT(2)))
{
q=1;
Y1_H;
Y2_H;
Y3_H;
g1=0;g2=0;g3=0;
tt1=0;tt2=0;tt3=0;
adc_max7219(); //只有按住停止按钮才能设置定时值
if(!(PIND&BIT(1)))//按住停止按钮 再按启动按钮
{
delay_ms(5);
if(!(PIND&BIT(1)))
{
Y3_L;
while(!(PIND&BIT(1)))WDR();
}
}
}
delay_ms(50);
}
if(!(PIND&BIT(1))&&(PIND&BIT(2))&&q)//启动按钮
{
delay_ms(10);
if(!(PIND&BIT(1))&&(PIND&BIT(2)))//启动按钮
{
while(!(PIND&BIT(1)))WDR();//等待启动按钮松开
Y3_L;Y1_L;g1=1;
}
}
//工作模式判断/////////////////////////////////////////////////////////////////
if(t1<tt1) //t1时间到
{
if(!(PIND&BIT(3))&&(PIND&BIT(0))) //高光模式(必须关掉走刀开关)
{
delay_ms(5);
if(!(PIND&BIT(3))&&(PIND&BIT(0)))
{
g1=0;
tt1=0;
Y1_H;
Y3_H;
}
}
else if(!(PIND&BIT(0))&&(PIND&BIT(3))) //否则为CD纹模式
{ //(判断走刀按钮,必须关掉走刀按钮)
delay_ms(5);
if(!(PIND&BIT(0))&&(PIND&BIT(3))) //再次判断
{
Y2_L;
if((PIND&BIT(1))&&(!(PIND&BIT(4)))) //行程开关(启动按钮必须松开)
{
delay_ms(5);
if((PIND&BIT(1))&&(!(PIND&BIT(4))))
{
g2=1;
if(t2<tt2) //t2时间到
{
Y1_H;Y3_H;g3=1;q=0;
if(t3<tt3) //t3时间到(启动按钮必须松开)
{
g1=0; g2=0; g3=0;
tt1=0;tt2=0;tt3=0;
Y2_H;q=1;
}
}
} }
}
}
}
///////////////////////////////////////////////////////////////////////////////
}
}
//定时器1的中断程序///给继电器定时用////////////////////////////////////////////
#pragma interrupt_handler timer1:9
void timer1(void)
{
TCNT1H=TEMERH;
TCNT1L=TEMERL;
if(g1)tt1++;
if(g2)tt2++;
if(g3)tt3++;
//系统闪烁灯
i++;
if(i>5) Y6_L;
if(i>10)
{
Y6_H;
i=0;
}
}