with Interrupt . txt
#include <avr/io.h>
#include <inttypes.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#include <avr/interrupt.h> // interrupt사용
#include <stdio.h>
#include <util/atomic.h>
#define CTC_MATCH_OVERFLOW ((F_CPU / 1000) / 8)
#define USART_BAUDRATE 9600 //블루투스 통신속도
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
//▼/////////////////////////////////
#include <stdlib.h>
#define EN PD5 //LCD의 EN핀
#define RS PD6 //LCD의 RS핀
void send_a_command(unsigned char command);
void send_a_character(unsigned char character);
void send_a_string(char *string_of_characters);
#define true 1
#define false 0
#define USART_RX_OFF 0
#define USART_RX_ECHO 1
volatile unsigned char usartRxMode = USART_RX_OFF;
volatile char usart_c;
char ReceivedByte;
volatile unsigned long timer1_millis;
long milliseconds_since;
ISR (TIMER1_COMPA_vect)
{
timer1_millis++;
}
unsigned long millis ()
{
unsigned long millis_return;
// Ensure this cannot be disrupted
//▼http://www.avrfreaks.net/forum/tut-newbies-guide-avr-interrupts?page=all
//▼http://www.avrfreaks.net/forum/bug-atomicblock-interrupt-xmega
//타이머 인터럽트와 연관되어있다.(OverFlow가 되면 강제적으로 ATOMIC_FORCEON 시킨다.)
ATOMIC_BLOCK(ATOMIC_FORCEON)
{
millis_return = timer1_millis;
}
return millis_return;
}
void timerinit(void)
{
// CTC mode, Clock/8
TCCR1B |= (1 << WGM12) | (1 << CS11);
// Load the high byte, then the low byte
// into the output compare
OCR1AH = (CTC_MATCH_OVERFLOW >> 8);
OCR1AL = CTC_MATCH_OVERFLOW;
// Enable the compare match interrupt
TIMSK |= (1 << OCIE1A);
//TIMSK-Timer/Counter Interrupt Mask Register
//OCIE1A : Output compare A match interrupt enable for Timer
}
void uartinit(void) //UART통신 초기화를 위한 Method
{
UCSR0B = (1 << RXEN) | (1 << TXEN);
// Turn on the transmission and reception circuitry
UCSR0C = (1 << UCSZ0) | (1 << UCSZ1);
// Use 8-bit character sizes
UBRR0H = (BAUD_PRESCALE >> 8);
// Load upper 8-bits of the baud rate value into the high byte of the UBRR register
UBRR0L = BAUD_PRESCALE;
// Load lower 8-bits of the baud rate value into the low byte of the UBRR register
UCSR0B |= (1 << RXCIE0);
// Enable the USART Recieve Complete interrupt (USART_RXC)
}
int i=0;
uint8_t data;
volatile uint8_t datareceived=false;
//uart enable의 역할을 한다. 그래서 초기값이 false이다.
uint8_t buzzerActive=false;
long buzzertime;
int main(void)
{
unsigned int i;
DDRA=0xFF; //Buzzer 출력 포트로 선언
DDRB = 0xff; // LCD Data Output
DDRC = 0b01100001; //Servo Output
DDRD = 0xFF; //LCD RS, EN pins
uartinit(); //위에서 선언된 Method 참고
//UCSR0A = 0x00;
//UCSR0B = 0x98;
//UCSR0C = 0x06;
//UBRR0H = 0x00;
//UBRR0L = 103;
//PORTC &= (0 >> PC0);
//ADC : Analog to Digital Conver
ADMUX |= (1<<REFS0) | (1<<REFS1);
ADCSRA |= (1<<ADEN)|(1<<ADFR)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2);
int16_t COUNTA = 0; //충격센서를 위한 변수 (0으로 초기화 시켰다.)
timerinit();
//LCD▼ 자세한 정보 링크입니다.
//http://instructables.tistory.com/560
send_a_command(0x01); //Clear Screen 0x01 = 00000001
_delay_ms(50);
send_a_command(0x38); //2 Line, 5x7 dots
_delay_ms(50);
send_a_command(0b00001111); //Display On, Cursor blinking
_delay_ms(50);
ADCSRA |=(1<<ADSC); //ADSC : ADC Start Conversion
//ADCSRA레지스터의 ADCS비트를 1로 set시킨다.
_delay_ms(100);
sei(); //Global Interrupt Enable (인터럽트 사용시 필요하다.)
while(1)
{
if(buzzerActive)
{
if(millis()-buzzertime>5000)
{
PORTA = 0b00000000;
buzzerActive=false;
}
}
else
{
COUNTA = ADC; //ADC/4;
if(COUNTA > 100) //충격센서가 충격값을 100이상 감지하면
{
//send_a_command(0x80 + 0x40 + 0);
////0x80:Force cursor to beginning of 1st row
send_a_command(0x01);//Clear Display Screen
send_a_command(0x80);//Force cursor to Beginning of 1st row
send_a_string("Shock");
// send_a_command(0x0F);//Cursor Blinking
////////////////////////////////////////////////////////
PORTA = 0b11111111; //Buzzer
buzzerActive=true;
buzzertime=millis();
}
else
{
//send_a_command(0x80 + 0x40 + 0);
////0x80:Force cursor to beginning of 1st row
send_a_command(0x01);//Clear Display Screen
send_a_command(0x80);//Force cursor to Beginning of 2nd row
send_a_string("Close");
// send_a_command(0x0F);//Cursor Blinking
////////////////////////////////////////////////////////
PORTA = 0b00000000; //Buzzer
}
}
if(datareceived)
{
if (ReceivedByte == '1') //id
{
//PORTB=0x01;
for(i=0; i<100; i++)
{
PORTC = 0x20; //0010 0000
_delay_us(600);
PORTC=0x00;
_delay_ms(23);
}
}
else if (ReceivedByte == '2')
{
//PORTB=0x00;
for(i=0; i<100; i++)
{
PORTC = 0x20;
_delay_us(2400); //_delay_us(1950);
PORTC = 0x00;
_delay_ms(23);
}
}
datareceived=false;
}
}
sei(); //Enable Global Interrupt
return 0;
} //End of main
ISR(USART0_RX_vect)
{
ReceivedByte = UDR0;
// Fetch the received byte value into the variable "ByteReceived"
UDR0 = ReceivedByte;
// Echo back the received byte back to the computer
datareceived=true;
}
//LCD//////////////////////////////
void send_a_command(unsigned char command)
{
PORTB = command;
PORTD &= ~(1<<RS); //111 0111
PORTD |= 1<<EN;
_delay_ms(20);
PORTD &= ~1<<EN;
PORTB = 0;
}
void send_a_character(unsigned char character)
{
PORTB = character;
PORTD |= 1<<RS; //위에서 define하였다. RS를 PD5라고
PORTD |= 1<<EN; //위에서 define하였다. EN를 PD6라고
_delay_ms(20);
PORTD &= ~1<<EN; //&= ~ 연산은 0으로 Reset시키는 연산이다.
PORTB = 0;
}
void send_a_string(char *string_of_characters)
{
while(*string_of_characters > 0)
{
send_a_character(*string_of_characters++);
}
}
'졸업작품 > 우편함(bluetooth+Servo+LCD+SmartPhone)' 카테고리의 다른 글
4.회로도 (7) | 2016.10.27 |
---|---|
3.AVR Studio에서 printf 사용하기 (0) | 2016.10.23 |
1.충격센서 (Piezo Disk Vibration Sensor) (0) | 2016.10.15 |