ElectricShock 2016. 10. 27. 15:17





with Interrupt . txt

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

 //http://www.engineersgarage.com/sites/default/files/imagecache/Original/wysiwyg_imageupload/1/ADMUX.JPG

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++);

}

}


Without Interrupt.txt