//The following is the program for the automatic water filling system. Use the infrared remote control to set the water level. Four scales can be set: 500g, 1000g, 1500g, and 2000g.
//Use the electrode method, that is, pass 12V into the water tank, place four wires on the set scale line, and connect them to the four I/O ports of Atmega16 respectively.
//Control the 12V water pump by controlling the 5V relay. When the water reaches the set water level, the water pump stops pumping, the buzzer sounds, and the LED light flashes.
#include
#include
#include
#include"12864.h"
#define BIT(bit) (1<<(bit))
uchar show_set_flag; //Show the set quality flag
uchar end_flag=1;
uchar end_count; //Number of times the water reaches the scale
uchar second,minute; //Seconds, minutes
uchar count;//Number of infrared decoded codes
uint now_quality,set_quality;//Actual quality, set quality
uint s_count;
uint date_code;//Address code and address inverse code obtained by infrared decoding
void display()//Display function
{
uchar shuju[5];
uchar i;
if(end_flag==0)//If end_flag==0, water starts to enter
{
shuju[0]=minute/10+48;//Tens digit
shuju[1]=minute%10+48;//Ones digit
shuju[2]=':';
shuju[3]=second/10+48;//Tens digit
shuju[4]=second%10+48;//Ones digit
set_position(0,3);
for(i=0;i<5;i++)
{
write_date(shuju[i]);
}
// write_date('g');
}
if(show_set_flag)//Display set quality
{
shuju[0]=set_quality/1000+48;//thousands
shuju[1]=set_quality/100%10+48;//hundreds
shuju[2]=set_quality%100/10+48;//tens
shuju[3]=set_quality%10+48;//units
set_position(1,5);
for(i=0;i<4;i++)
{
write_date(shuju[i]);
}
write_date('g');
set_position(3,0);
show_string(" ");
show_set_flag=0;
}
// set_position(1,0);
// show_string(L7);//display string
}
void quality_display()//display of current quality
{
uchar zhiliang[4];
uchar i;
zhiliang[0]=now_quality/1000+48;//thousands
digitzhiliang[1]=now_quality/100%10+48;//hundreds
digitzhiliang[2]=now_quality%100/10+48;//tens
digitzhiliang[3]=now_quality%10+48;//units
digitset_position(2,5);
for(i=0;i<4;i++)
{
write_date(zhiliang[i]);
}
write_date('g');
}
void Bee()//buzzer alarm, when the set water level is reached, the buzzer sounds and the LED flashes
{
uchar i,j;
for(j=0;j<7;j++)
{
for(i=0;i<100;i++)
{
PORTB^=BIT(PB0);
_delay_ms(3);
}
}
}
void moden_500g()//set the water level to 500g mode
{
if(!(PINB&BIT(PB1)))//Judge whether the water level has reached the 500g mark
{
// if((PINB&BIT(PB2)==1)&&(PINB&BIT(PB3)===1)&&(PINA&BIT(PA3)==1)
_delay_ms(5);//Delay to prevent misoperationif
(!(PINB&BIT(PB1)))//Judge again whether the water level has reached the scale
{
PORTD&=~(BIT(PD0)|BIT(PD1));//Output 0, i.e. close the solenoid valve
end_flag=1;
TIMSK&=~BIT(TOIE0);//Disable timer 0 overflow interrupt enable
now_quality=500;
quality_display();
set_position(3,0);
show_string("reached set quality");
Bee();
end_count=1;
}
}
}
void moden_1000g()//Set the water level to 1000g mode
{
if(end_count==0)//Judge whether the water level has reached the 500g scale
{
if(!(PINB&BIT(PB1)))
{
_delay_ms(5);
if(!(PINB&BIT(PB1)))
{
end_count=1;
now_quality=500;
quality_display();
}
}
}
else//If the water level exceeds 500g but has not reached the 1000g scale
{
//if((PINB&BIT(PB1)==0)&&(PINB&BIT(PB3)===1)&&(PINA&BIT(PA3)==1)
if(!(PINB&BIT(PB2)))//Judge whether the water level has reached the 1000g scale
{
_delay_ms(5);
if(!(PINB&BIT(PB2)))
{
PORTD&=~(BIT(PD0)|BIT(PD1));//Output 0, i.e. close the solenoid valveend_flag
=1;
TIMSK&=~BIT(TOIE0);//Disable timer 0 overflow interrupt
enablenow_quality=1000;
quality_display();
set_position(3,0);
show_string("reached the set quality");
Bee();
end_count=2;
}
}
}
}
void moden_1500g()//Set the water level to 1500g mode
{
if(end_count==0)//Judge whether the water level has reached the 500g scale
{
if(!(PINB&BIT(PB1)))
{
_delay_ms(5);
if(!(PINB&BIT(PB1)))
{
end_count=1;
now_quality=500;
quality_display();
}
}
}
else if(end_count<2)//If the water level exceeds 500g but has not reached the 1000g scale
{
if(!(PINB&BIT(PB2)))//Judge whether the water level has reached the 1000g scale
{
_delay_ms(5);
if(!(PINB&BIT(PB2)))
{
end_count=2;
now_quality=1000;
quality_display();
}
}
}
else //If the water level exceeds the 1000g mark but does not reach the 1500g mark
{
if(!(PINB&BIT(PB3)))//Judge whether the water level has reached the 1500g mark
{
_delay_ms(5);
if(!(PINB&BIT(PB3)))
{
PORTD&=~(BIT(PD0)|BIT(PD1));//Output 0, i.e. close the solenoid valveend_flag
=1;
TIMSK&=~BIT(TOIE0);//Disable timer 0 overflow interrupt enablenow_quality
=1500;
quality_display();
set_position(3,0);
show_string("Arrived at the set quality");
Bee();
end_count=3;
}
}
}
}
void moden_2000g()//Set the water level to 2000g mode
{
if(end_count==0)//Judge whether the water level has reached the 500g scale
{
if(!(PINB&BIT(PB1)))
{
_delay_ms(5);
if(!(PINB&BIT(PB1)))
{
end_count=1;
now_quality=500;
quality_display();
}
}
}
else if(end_count<2)//If the water level exceeds 500g but has not reached the 1000g scale
{
if(!(PINB&BIT(PB2)))
{
_delay_ms(5);
if(!(PINB&BIT(PB2)))
{
end_count=2;
now_quality=1000;
quality_display();
}
}
}
else if(end_count<3)//If the water level exceeds the 1000g mark but does not reach the 1500g mark
{
if(!(PINB&BIT(PB3)))
{
_delay_ms(5);
if(!(PINB&BIT(PB3)))
{
end_count=3;
now_quality=1500;
quality_display();
}
}
}
else //If the water level exceeds the 1500g mark but does not reach the 2000g mark
{
if(!(PINA&BIT(PA3)))//Judge whether the water level has reached the 2000g mark
{
_delay_ms(5);
if(!(PINA&BIT(PA3)))
{
PORTD&=~(BIT(PD0)|BIT(PD1));//Output 0, i.e. close the solenoid
valveend_flag=1;
TIMSK&=~BIT(TOIE0); //Disable timer 0 overflow interrupt enable
now_quality=2000;
quality_display();
set_position(3,0);
show_string("reached set quality");
Bee();
end_count=4;
}
}
}
}
void init()//initialization function
{
DDRA|=BIT(PA7)|BIT(PA6)|BIT(PA5);//Set the 6th bit of PA port (RS control pin of 12864) and the 7th bit (EN control pin of 12864) to output
DDRA&=~BIT(PA3);//Set the 3rd bit of PA port to input, connect to the water level line
PORTA|=BIT(PA3);//Enable the pull-up resistor of the 3rd bit of PA port
DDRB&=~(BIT(PB1)|BIT(PB2)|BIT(PB3));//PB port 1, 2, 3 bits are input, connect to the water level line
DDRB|=BIT(PB0);//Set PB0 port to output, control the buzzer and LED
PORTB&=~BIT(PB0);//PB0 port outputs 0, turns off the buzzer and LED
PORTB|=BIT(PB1)|BIT(PB2)|BIT(PB3);//Enable the pull-up resistor of the high four bits of the PD port
DDRC=0xff;//Set all to output
DDRD&=~BIT(PD6);//Set the ICP1 pin to input
DDRD|=BIT(PD0)|BIT(PD1);//Set PD0 and PD1 ports to output, control the relay and then control the solenoid valve
PORTD|=BIT(PD6);//Enable the pull-up resistor of the ICP1 pin
PORTD&=~(BIT(PD0)|BIT(PD1));//Output 0, that is, close the solenoid valve
TCNT1=0;//Initial value is 0
TIMSK=BIT(TICIE1)|BIT(TOIE0);//Input capture interrupt enable, timer 0 overflow interrupt enable;
sei(); //Open the total interrupt
TCCR1B=BIT(ICNC1)|BIT(CS11); //8 division, and start timer 1. After 8 division, the 8M crystal oscillator counts at a speed of 1M, that is, it counts once every 1us.
// TCNT0=55; //The initial value is 55, that is, it counts 255-55=200 times, overflows and enters the timer 0 interrupt function
// TCCR0|=_BV(CS01); //8 division, and start timer 0. After 8 division, the 8M crystal oscillator counts at a speed of 1M, that is, it counts once every 1us, and counting 100 times is 100us, that is, it enters the timer 0 interrupt function once every 100us
init_12864(); //12864 LCD initialization
set_position(0,0);
show_string("Time: "); //Display string
set_position(1,0);
show_string("Quality settings: ");
set_position(2,0);
show_string("Quality: ");
}
int main()
{
init();
while(1)
{
if(end_flag==0)
{
switch(set_quality)
{
case 500:moden_500g();break;//Set the water level to 500g mode
case 1000:moden_1000g();break;//Set the water level to 1000g mode
case 1500:moden_1500g();break;//Set the water level to 1500g mode
case 2000:moden_2000g();break;//Set the water level to 2000g mode
}
}
display();//Display
}
}
volatile uint ICP_lastValue=0,ICP_value=0,time=0;
ISR(TIMER1_CAPT_vect)//ICP input capture interrupt function, input pin is ICP1 PD6 (pin 20)
{
ICP_value=ICR1;//Read the time when the ICP input capture event occurs
if(ICP_lastValue>ICP_value)time=0xffff-ICP_lastValue+1+ICP_value;//Calculate the time taken between two falling edges
else time=ICP_value-ICP_lastValue;
//TIFR|=BIT(ICF1);//This statement is optional, because ICF1 is automatically cleared to 0 when the interrupt is executed, and this statement can also be used to implement software clearing
ICP_lastValue=ICP_value;
if(time>950&&time<1225)time=0;
else if(time>2050&&time<2345)time=1;
else if(time>13325&&time<13600)//Judge the leading code
{
date_code=0;
count=0;
return;
}
else {return;}//Remove interference. This statement works when the falling edge and the end code when preparing to enter the leading code are received. Without this statement, it can only receive once
count++;
if(count>16&&count<32)
{
date_code=date_code|time;
date_code=date_code<<1;
}
else if(count==32)//Receive 32 bits
{
date_code=date_code|time;
PORTB^=BIT(PB0);
_delay_ms(7);
PORTB^=BIT(PB0);
_delay_ms(7);
if(end_flag)
{
switch(date_code)
{
case 0x807f:set_quality=500; show_set_flag=1;break;//1
case 0x40bf:set_quality=1000;show_set_flag=1;break;//2
case 0xc03f:set_quality=1500;show_set_flag=1;break;//3
case 0x20df:set_quality=2000;show_set_flag= 1;break;//4
case 0x30cf:{
if(set_quality>now_quality)
{
s_count=0;
second=0;
minute=0;
end_flag=0;
TIMSK|=BIT(TOIE0); //Enable timer 0 overflow interrupt
TCNT0=55; //The initial value is 55, that is, count 255-55=200 overflows and enter the timer 0 interrupt function
TCCR0|=BIT (CS01); //8 division, and start timer 0. After 8M crystal is divided by 8, it counts at a speed of 1M, that is, it counts once every 1us, and 100 times is 100us, that is, 100us Enter the timer 0 interrupt function
PORTD|=BIT(PD0)|BIT(PD1); //output 1, that is, open the solenoid valve to let water flow into the tank
}
else
{
set_position(3,0);
show_string("Please reset");
}
break;
}
}
}
}
}
SIGNAL(SIG_OVERFLOW0)//Timer 0 interrupt service function
{
TCNT0=55;
s_count++;
if(s_count>=4900)
{
s_count=0;
second++;
if(second==60)
{
second=0;
minute++;
if(minute==60)
{
minute=0;
}
}
}
}
//12864 LCD display header file
#define uchar unsigned char
#define uint unsigned int
//Bit 5 of PA port (parallel/serial interface selection control pin of 12864)
#define PSB PORTA |= (1 << 5) //Bit 5 outputs high level parallel port mode
//Bit 6 of PA port (RS control pin of 12864) and bit 7 (EN control pin of 12864)
//Data command end
#define lcdrs_L PORTA &= ~(1 << 6) //Bit 6 outputs low level command
#define lcdrs_H PORTA |= (1 << 6) //Bit 6 outputs high level data
//Enable end
#define lcden_L PORTA &= ~(1 << 7) //Bit 7 outputs low level disable enable
#define lcden_H PORTA |= (1 << 7) //Bit 7 outputs high level enable void
write_com(uchar com)//write command function
{
lcdrs_L;
PORTC=com;
_delay_ms(5);
lcden_H;
_delay_ms(5);
lcden_L;
}
void write_date(uchar date)//write data function
{
lcdrs_H;
PORTC=date;
_delay_ms(5);
lcden_H;
_delay_ms(5);
lcden_L;
}
void init_12864()//12864 LCD initialization function
{
PSB;//parallel port mode
lcden_L;//enable first
write_com(0x30);//basic instruction set expansion instruction set is 0x34
_delay_ms(5);
write_com(0x01);//clear screen
_delay_ms(5);
write_com(0x0c);//turn on display, do not display cursor, cursor does not blink
_delay_ms(5);
write_com(0x02);//Clear the address counter and put the cursor back to the origin
_delay_ms(5);
write_com(0x80);//Start displaying from this address Start displaying from the origin
_delay_ms(5);
//write_com(0x18); Execute once, the whole screen moves left once
//write_com(0x1c); Execute once, the whole screen moves right once
}
void set_position(uchar x, uchar y)
{
uchar position=0;
switch(x%4)
{
case 0: position=0x80;break; //first line start address
case 1: position=0x90;break; //second line
case 2: position=0x88;break; //third line
case 3: position=0x98;break; //fourth line
}
position+=y;//coordinates to be displayed
write_com(position);
}
void show_string(uchar *string)//display string function
{
while(*string)
{
write_date(*string++);
}
}
Previous article:Atmega16 Timer 0 usage
Next article:IR remote control decoding with Atmega16 input capture function
Recommended ReadingLatest update time:2024-11-16 14:58
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- How to install virtual machine on SinA33 development board
- Newbie asks for advice on STC89c54RD+, RAM access value application
- The problem of sensor sampling value software returning to zero
- Several indoor wireless positioning technologies
- NXP Rapid IoT Review] +4. Learn the design ideas of POWER circuits
- HTS221 self-heating function test
- Understanding the configuration of C2000 series CMD files
- [Xiaomeige SoC] Generate preloader under win10 and report Failed to open gdrive/…/uboot-socfpga.tar.gz
- Looking for a voltage detection circuit or chip, 3v to 12v
- You must call ros::init() before creating the first NodeHandle