第4步编写代码
我编写的代码见附件
/***
PIN ASSIGNMENTS ON ATMEGA48
PC6 (PCINT14/RESET)
PC5 (ADC5/SCL/PCINT13) // I2C时钟输入
PC4 (ADC4/SDA/PCINT12) // I2C数据输入
PC3 (ADC3/PCINT11) //传感器 4 IR 接收器
PC2 (ADC2/PCINT10)
PC1 (ADC1/PCINT9)
PC0 (ADC0/PCINT8)
PB7 (PCINT7/XTAL2/TOSC2) //IR 4 触发
PB6 (PCINT6/XTAL1/TOSC1) //IR 3 触发
PB5 (SCK/PCINT5)
PB4 (MISO/PCINT4)
PB3 (MOSI/OC2A/PCINT3) //PWM 3
PB2 (SS/OC1B/PCINT2)
PB1 (OC1A/PCINT1)
PB0 (PCINT0/CLKO/ICP1)
PD0 (PCINT16/RXD)
PD1 (PCINT17/TXD)
PD2 (PCINT18/INT0)
PD3 (PCINT19/OC2B/INT1) //PWM 4
PD4 (PCINT20/XCK/T0)
PD5 (PCINT21/OC0B/T1) //PWM 2
PD6 (PCINT22/OC0A/AIN0) //PWM 1
PD7 (PCINT23/AIN1)
***/
#define IR_1_ON PORTB |= (1<<4)
#define IR_2_ON PORTB |= (1<<5)
#define IR_3_ON PORTB |= (1<<6)
#define IR_4_ON PORTB |= (1<<7)
#define IR_1_OFF PORTB &= ~(1<<4)
#define IR_2_OFF PORTB &= ~(1<<5)
#define IR_3_OFF PORTB &= ~(1<<6)
#define IR_4_OFF PORTB &= ~(1<<7)
#define PWM1 6 //PORTD PWM引脚分配
#define PWM2 5 //PORTD
#define PWM3 3 //PORTB
#define PWM4 3 //PORTD
#define F_CPU 8000000UL
#include
#include
#include
//#include
/****Function Declarations****/
int ADC_read(void);
void A2D_Channel_Select(unsigned char channel);
void Init_ADC(void);
void Init_Timer0(void);
void Init_Timer1(void);
void Init_Timer2(void);
void Delay(void);
void Calibrate_Sensors(void);
//void Init_I2C_Slave_Rx(void);
/****Global Variable Declarations****/
volatile char Sensor_Values_Updated = 0;
volatile char Timer1_Overflow = 0;
volatile unsigned char channel = 0;
volatile int Amb_Sensor_1 = 0, Amb_Sensor_2 = 0, Amb_Sensor_3 = 0, Amb_Sensor_4 = 0;
volatile int Sensor_1 = 0, Sensor_2 = 0, Sensor_3 = 0, Sensor_4 = 0;
volatile int Initial_1 = 0, Initial_2 = 0, Initial_3 = 0, Initial_4 = 0;
volatile int New_PWM1 = 0, New_PWM2 = 0, New_PWM3 = 0, New_PWM4 = 0;
volatile int Old_PWM1 = 0, Old_PWM2 = 0, Old_PWM3 = 0, Old_PWM4 = 0;
unsigned char buffer = 8;
int main(void)
{
DDRB = 0xff;
//make sure IR emitters are turned off, and PWM 3
PORTB &= ~((1 << 7)|(1 << 6)|(1 << 5)|(1 << 4)|(1 << 3));
DDRC = 0x00;
DDRD = 0xff;
PORTD = 0x00; //使所有PORT D为低
Init_ADC();
sei();
Calibrate_Sensors();
PORTD |= (1 << PWM1);
_delay_ms(600);
PORTD &= ~(1 << PWM1);
Init_Timer0();
Init_Timer2();
//Init_I2C_Slave_Rx();
while(1)
{
//do something?
//. . .
}
}
ISR(TIMER1_OVF_vect)
{
Timer1_Overflow++;
switch(Timer1_Overflow)
{
case 1:
A2D_Channel_Select(0); //select ADC channel 0
Amb_Sensor_1 = ADC_read();
IR_1_ON; //turn on IR 1 LED, PORTB |= (1<<4)
Delay(); //delay for the IR receiver to settle
Sensor_1 = ADC_read(); //take active ADC reading of IR receiver
IR_1_OFF; //turn off IR 1 LED
New_PWM1 = (Sensor_1 - Amb_Sensor_1) - Initial_1; //condition readings
if(New_PWM1 <= 0) { New_PWM1 = 0; }
New_PWM1 = ((7*Old_PWM1)>>3) + (New_PWM1>>3);
if(OCR0A >= 1) {DDRD |= (1 << PWM1);}
else { DDRD &= ~(1 << PWM1); } New_PWM1 <<= 2;
if(New_PWM1 > 255) { New_PWM1 = 255; }
OCR0A = New_PWM1;
New_PWM1 >>= 2;
/***** //Trigger sequence
if(New_PWM1 > Initial_1)
{
DDRD |= (1 << PWM1);
if(OCR0A < 255)
{
OCR0A += (255 - OCR0A)>>2 ;
//OCR0A++;
}
if (New_PWM1 < (Initial_1 + 8))
{
Initial_1 = ((7*Initial_1)>>3) + (New_PWM1>>3);
}
}
else if(New_PWM1 < Initial_1)
{
if(OCR0A > 0)
{
OCR0A -= (OCR0A >> 4)+1;
//OCR0A--;
}
else if(OCR0A <= 0)
{
DDRD &= ~(1 << PWM1);
}
}
*****/
Old_PWM1 = New_PWM1;
break;
case 2:
A2D_Channel_Select(1); //select ADC channel 1
Amb_Sensor_2 = ADC_read();
IR_2_ON; //turn on IR 2 LED, PORTB |= (1<<5)
Delay(); //delay for the IR receiver to settle
Sensor_2 = ADC_read(); //take ADC reading
IR_2_OFF; //turn off IR 2 LED
New_PWM2 = (Sensor_2 - Amb_Sensor_2) - Initial_2;
if(New_PWM2 < 0) { New_PWM2 = 0; }
New_PWM2 = ((7*Old_PWM2)>>3) + (New_PWM2>>3);
if(OCR0B >= 1) {DDRD |= (1 << PWM2);}
else { DDRD &= ~(1 << PWM2); }
New_PWM2 <<= 2;
if(New_PWM2 > 255) { New_PWM2 = 255; }
OCR0B = New_PWM2;
New_PWM2 >>= 2;
/*
if(New_PWM2 > Initial_2)
{
DDRD |= (1 << PWM2);
if(OCR0B < 255)
{
OCR0B += (255 - OCR0B)>>2 ;
//OCR0B++;
}
if (New_PWM2 < (Initial_2 + 8))
{
Initial_2 = ((7*Initial_2)>>3) + (New_PWM2>>3);
}
}
else if(New_PWM2 < Initial_2)
{
if(OCR0B > 0)
{
OCR0B -= (OCR0B >> 4)+1;
//OCR0B--;
}
else if(OCR0B <= 0)
{
DDRD &= ~(1 << PWM2);
}
}
*/
Old_PWM2 = New_PWM2;
break;
case 3:
A2D_Channel_Select(2); //select ADC channel 2
Amb_Sensor_3 = ADC_read();
IR_3_ON; //turn on IR 3 LED, PORTB |= (1<<6)
Delay(); //delay for the IR receiver to settle
Sensor_3 = ADC_read(); //take ADC reading
IR_3_OFF; //turn off IR 3 LED
New_PWM3 = (Sensor_3 - Amb_Sensor_3) - Initial_3;
if(New_PWM3 < 0) { New_PWM3 = 0; }
New_PWM3 = ((7*Old_PWM3)>>3) + (New_PWM3>>3);
if(OCR2A >= 1) {DDRB |= (1 << PWM3);}
else { DDRB &= ~(1 << PWM3); }
New_PWM3 <<= 2;
if(New_PWM3 > 255) { New_PWM3 = 255; }
OCR2A = New_PWM3;
New_PWM3 >>= 2;
/*
if(New_PWM3 > Initial_3)
{
DDRB |= (1 << PWM3);
if(OCR2A < 255)
{
OCR2A += (255 - OCR2A)>>2 ;
//OCR2A++;
}
if (New_PWM3 < (Initial_3 + 8))
{
Initial_3 = ((7*Initial_3)>>3) + (New_PWM3>>3);
}
}
else if(New_PWM3 < Initial_3)
{
if(OCR2A > 0)
{
OCR2A -= (OCR2A >> 4)+1;
//OCR2A--;
}
else if(OCR2A <= 0)
{
DDRB &= ~(1 << PWM3);
}
}
*/
Old_PWM3 = New_PWM3;
break;
case 4:
A2D_Channel_Select(3); //select ADC channel 3
Amb_Sensor_4 = ADC_read();
IR_4_ON; //turn on IR 4 LED, PORTB |= (1<<7)
Delay(); //delay for the IR receiver to settle
Sensor_4 = ADC_read(); //take ADC reading
IR_4_OFF; //turn off IR 4 LED
New_PWM4 = (Sensor_4 - Amb_Sensor_4) - Initial_4;
if(New_PWM4 < 0) { New_PWM4 = 0; }
New_PWM4 = ((7*Old_PWM4)>>3) + (New_PWM4>>3);
if(OCR2B >= 1) {DDRD |= (1 << PWM4);}
else { DDRD &= ~(1 << PWM4); }
New_PWM4 <<= 2;
if(New_PWM4 > 255) { New_PWM4 = 255; }
OCR2B = New_PWM4;
New_PWM4 >>= 2;
/*
if(New_PWM4 > Initial_4)
{
DDRD |= (1 << PWM4);
if(OCR2B < 255)
{
OCR2B += (255 - OCR2B)>>2 ;
//OCR2B++;
}
if (New_PWM4 < (Initial_4 + 8))
{
Initial_4 = ((7*Initial_4)>>3) + (New_PWM4>>3);
}
}
else if(New_PWM1 < Initial_4)
{
if(OCR2B > 0)
{
OCR2B -= (OCR2B >> 4)+1;
//OCR2B--;
}
else if(OCR2B <= 0)
{
DDRD &= ~(1 << PWM4);
}
}
*/
Old_PWM4 = New_PWM4;
Timer1_Overflow = 0;
Sensor_Values_Updated = 1;
break;
}//end switch
}//end ISR
/****
ISR(TWI_vect) //to include later when I get this figured out
{
switch(TWSR)
{
case TW_SR_SLA_ACK: //0x60 //Own address Rx
Byte_Number == 1;
break;
case TW_SR_DATA_ACK: // 0x80 , data in TWDR
switch(Byte_Number)
{
case 1:
Reg_Addr = TWDR;
Byte_Number++;
break;
case 2:
Reg_Val = TWDR;
Byte_Number = 0; //reset, unless more bytes are coming
break;
case Max_Bytes_Expected:
Reg_Val = TWDR;
Byte_Number = 0; //reset, unless more bytes are coming
break;
}
break;
case TW_SR_GCALL_DATA_ACK: // 0x90
if(Byte_Number == 1)
{
Reg_Addr = TWDR;
Byte_Number++;
}
else if(Byte_Number == 2)
{
Reg_Val = TWDR;
Byte_Number = 0; //reset, unless more bytes are coming
}
break;
}//end switch
}//end ISR
void Init_I2C_Slave_Rx(void)
{
//Set Device Address in TWAR
TWAR = 10;
TWCR |= ((1 << TWEA)|(1 << TWEN));
TWCR &= ~((1 << TWSTA)|(1 << TWSTO));
}
****/
void Calibrate_Sensors(void) //establish initial ambient sensor values
{
char q = 0;
Init_Timer1();
for(q=0; q<32; q++) //should take one second-ish
{
//wait for Sensor cycle to be done, then gather sensors values
while(Sensor_Values_Updated == 0) {}
Initial_1 += (Sensor_1 - Amb_Sensor_1); //initial difference
Initial_2 += (Sensor_2 - Amb_Sensor_2);
Initial_3 += (Sensor_3 - Amb_Sensor_3);
Initial_4 += (Sensor_4 - Amb_Sensor_4);
Sensor_Values_Updated = 0; //reset
}
//condition Initial Ambient Sensor values, plus a buffer
Initial_1 = (Initial_1 >> 5) + buffer;
Initial_2 = (Initial_2 >> 5) + buffer;
Initial_3 = (Initial_3 >> 5) + buffer;
Initial_4 = (Initial_4 >> 5) + buffer;
}
void Init_ADC(void)
{
ADMUX |= 1 << REFS0; //AVCC with external capacitor at AREF pin
ADMUX |= (1<
}
void Init_Timer0(void)
{
//Fast PWM, non-inverting, WGM02-WGM00 == 011, no overflow interrupt
TCCR0A |= ((1 << COM0A1)|(1 << COM0B1)|(1 << WGM01)|(1 << WGM00));
TCCR0B |= (1 << CS00); //start clock, no prescale
}
void Init_Timer1(void)
{
//no PWM, enable overflow interrupt,
//TOP == 0xFFFF == 65536 cycles == roughly 122 overflow interrupts/sec
TCCR1B |= (1 << CS10);
TIMSK1 |= (1 << TOIE1);
}
void Init_Timer2(void) //PWM for sensors 3 & 4
{
//Fast PWM, non-inverting, WGM22-WGM20 == 011, no overflow interrupt
TCCR2A |= ((1 << COM2A1)|(1 << COM2B1)|(1 << WGM21)|(1 << WGM20));
TCCR2B |= (1 << CS20); //start clock, no prescale
}
int ADC_read(void) /***select ADC channel prior to calling this function***/
{
int ADC_value = 0;
int ADCsample;
char i;
ADCSRA |= (1< ADCSRA |= (1< while ((ADCSRA & ADSC));
for (i=0; i<64; i++)
{
ADCSRA |= (1< while ((ADCSRA & ADSC)); //wait for conversion to finish
//change back to ADCL for 10 bit precision, and remove left-shift bit setting
ADCsample = ADCH;
//ADCsample += (ADCH<<8);
ADC_value += ADCsample; //add ADCsample to ADC_sensor
}
return ADC_value;
ADCSRA &= ~(1<
void A2D_Channel_Select(unsigned char channel)
{
switch (channel)
{
case 0:
ADMUX &= ~((1 << 3)|(1 << 2)|(1 << 1)|(1 << 0));
break;
case 1:
ADMUX &= ~((1 << 3)|(1 << 2)|(1 << 1));
ADMUX |= (1 << 0);
break;
case 2:
ADMUX &= ~((1 << 3)|(1 << 2)|(1 << 0));
ADMUX |= (1 << 1);
break;
case 3:
ADMUX &= ~((1 << 3)|(1 << 2));
ADMUX |= ((1 << 1)|(1 << 0));
break;
/* I am not using these for this project
case 4:
ADMUX &= ~((1 << 3)|(1 << 1)|(1 << 0));
ADMUX |= (1 << 2);
break;
case 5:
ADMUX &= ~((1 << 3)|(1 << 1));
ADMUX |= ((1 << 2)|(1 << 0));
break;
*/
}//end switch
}
void Delay(void)
{
_delay_us(100);
}猜你会喜欢
简单的光线探测器
光线探测器是最普遍的传感器之一,并广泛应...
无线供电的LED旋转时钟
这次的制作结合了无线供电的原理和时钟功能...
发光圣诞树
圣诞节就要来了,你还没有圣诞树么?现在就...
高手打造的智能无线供电台灯
无线供电是一个很吸引人的制作课题,许多电...
世界上最小的DS18B20温度计
DS18B20不少朋友都用过吧,不过似乎...

















评 论
选择昵称后请轻按空格键
请勿进行人身攻击,谩骂以及任何违法国家相关法律法规的言论。