#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求平均的個數
#define N 3
//數碼管亮度調節0x00-0xff
#define P 0x01
uint t1,t2,t3,t4,tt1,tt2,tt3,tt4;
uint addata,adc;
uchar g1,g2,g3,g4;
////////////////////////////////////////////////////////////////////////////////
void port_init()
{
DDRC&=BIT(0)&BIT(1)&BIT(2)&BIT(3); //AD轉換口設置為輸入、無上拉
PORTC&=BIT(0)&BIT(1)&BIT(2)&BIT(3);
DDRD|=0x3f;
PORTD|=0x3f; //配置PD口為輸入,有上拉電阻
DDRD&=0xC0;
//Y1_OUT;Y2_OUT;Y3_OUT;Y4_OUT;Y5_OUT;Y6_OUT;
// Y1_H;Y2_H;Y3_H;Y4_H;Y5_H;Y6_H;
}
//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
delay_ms(100);
}
//定時器1初始化子程序///////////////////////////////////////////////////////////
void init_timer1()
{
TCCR1B|=0x04;//256分頻
TCNT1H=0xff;//高8位初值
TCNT1L=0x03;//低8位初值
TIMSK|=BIT(2);//定時器1的中斷使能
}
//定時器0初始化子程序///////////////////////////////////////////////////////////
void init_timer0()
{
TCCR0|=0x04;//256分頻
TCNT0=0x00;//初值
TIMSK|=BIT(0);//定時器0的中斷使能
}
//延時函數//////////////////////////////////////////////////////////////////////
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);
}
//切換ADC通道采集四個電位器的值送數碼管顯示//////////////////////////////////////
void adc_max7219()
{
uchar shi1=0, ge1=0; //定義2個局部變量
t1=Mega8_ad(0X40); //選擇PA0為AD通道,將轉換結果賦給t1
max7219(2,t1/10); max7219(1,t1%10);
delay_ms(2);
t2=Mega8_ad(0X41);
max7219(4,t2/10);max7219(3,t2%10);
delay_ms(2);
t3=Mega8_ad(0X42);
max7219(6,t3/10);max7219(5,t3%10);
delay_ms(2);
t4=Mega8_ad(0X43);
max7219(8,t4/10);max7219(7,t4%10);
delay_ms(2);
}
//主函數////////////////////////////////////////////////////////////////////////
void main()
{
port_init(); //初始化io
initmax7219(); //初始化max7219
//init_timer0(); //初始化定時器0
init_timer1(); //初始化定時器1
SREG|=BIT(7); //打開總中斷
Mega8_ad(0X40); //啟動一次通道0的AD轉換
Mega8_ad(0X41); //啟動一次通道1的AD轉換
Mega8_ad(0X42); //啟動一次通道2的AD轉換
Mega8_ad(0X43); //啟動一次通道3的AD轉換
while(1)
{
adc_max7219();
///////////////////////////////////////////////////////////////////////////////
if(!(PIND&BIT(1)))//啟動按鈕
{
delay_ms(10);
if(!(PIND&BIT(1)))//啟動按鈕
{
while(!(PIND&BIT(1)));
Y1_OUT;Y1_L;g1=1;
}
}
if(!(PIND&BIT(2)))//停止按鈕
{
Y1_OUT;Y1_H;
Y2_OUT;Y2_H;
Y3_OUT;Y3_H;
Y4_OUT;Y4_H;
g1=0;g2=0;g3=0;g4=0;
tt1=0;tt2=0;tt3=0;tt4=0;
}
if(t3<tt3)//工作模式判斷///車CD紋///高光
{
if(!(PIND&BIT(3))){ g1=0;tt3=0;Y1_OUT;Y1_H;}
// else
//{
if(!(PIND&BIT(4))){g1=0;tt3=0;Y2_OUT;Y2_L;}
//}
}
if(!((PIND&BIT(5))|(PIND4&BIT(4)))) g2=1;//行程開關
if(t2<tt2){g2=0;tt2=0;Y1_OUT;Y1_H;g3=1;}
if(t1<tt1){g3=0;tt1=0;Y2_OUT;Y2_H;}
///////////////////////////////////////////////////////////////////////////////
}
}
//定時器0的中斷程序////刷新AD轉換的值和刷新數碼管用/////////////////////////////
#pragma interrupt_handler timer0:10
void timer0(void)
{
TCNT0=0X00;
}
//定時器1的中斷程序///給繼電器定時用////////////////////////////////////////////
#pragma interrupt_handler timer1:9
void timer1(void)
{
TCNT1H=0xff;
TCNT1L=0x03;
if(g1)tt3++;
if(g2)tt2++;
if(g3)tt1++;
}