[ create a new paste ] login | about

Link: http://codepad.org/g88FNK63    [ raw code | fork ]

C, pasted on Feb 20:
/*
 *  target cpu: atmega168
 *  registers like UCSR0A are named differently on a atmega32 for example, watch out!
 *
 *  this code receives data over the uart from a HC-05 bluetooth module
 *  and switches on led1 if the character that was received is: h
 *  and led2 if the character is z
 *
 *
 *  ----
 *  tested with:
 *      bluetooth terminal
 *      qwerty.bluetooth terminal
 *
 *      i know the name looks stupid, but thats how the coder decided to go
 *      https://play.google.com/store/apps/details?id=Qwerty.BluetoothTerminal&hl=en
 *
 *      version: 6.1104
 *      e-mail: aries156@gmail.com  
 *
 *  in the setup, activate '\r\n' line endings
 *  note: tested other bluetooth apps, but this free one just worked
 *
 *  to use the software:
 *      ONLY THE FIRST TIME: you need to "pair" the devices - for whatever reason, bluetooth likes to get to know each other
 *      when you first make contact (like that worked out with the bork) - so you "pair" your device with a PIN code.
 *      the hc05 modules pin code is the extremely secure "1234" just to make pairing absolutely useless. (from a security point of view)
 *
 *
 *      start the app, choose: connect a device - insecure
 *      select your hc-05 module (default name: HC-05)
 *      type a h to activate led1
 *      type a z to activate led2
 *  ----
 *
 *  circuit:
 *      hc05 rx -> atmega168 tx (PD1)
 *      hx05 tx -> atmega168 rx (PD0)
 *
 *  voltages:
 *      5V supply voltage:
 *          i was running the circuit at 5V, so i needed a voltage devider between the atmega TX and the HC05 RX
 *          to get the voltage down from 5v to about 3.3v
 *
 *          the modules operating voltage is 3.3v - 6v, so yes you can attach 5v to VCC of the module
 *          but the voltage for the RX on the HC05 is 3.3V - so do a voltage divider
 *      3.3v supply voltage:
 *          NOT TESTED, but should work just fine. skip the voltage divider.
 *
 *  ----
 *
 *
 *
 *  code by: julius junghans
 */
 
 

// atmega 168


#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>

// you always read online that the modules are preset to 9600 bauds, i just found one source who said otherwies.
// but that source could have been confused by the fact that the AT command mode works with 38400
#define BAUD 9600
/*
 * dont forget to define F_CPU in the Makefile.
 * something like:
 * F_OSC = 16000000
 * F_CPU = $(F_OSC)
 * CFLAGS = -mmcu=$(DEVICE) -DF_CPU=$(F_CPU)
 * 
 * sometimes F_OSC is used, probably just another name for F_CPU
 */

#define MYUBRR ((uint16_t) ((F_CPU / ((BAUD) * 16.0)) + .5) - 1)
#define LED1 PB0
#define LED2 PB1


// contains what the bluetooth module received
uint8_t data;

void USART_Init(unsigned int ubrr)
{
    // set baud rate
    UBRR0H = (unsigned char)(ubrr>>8);
    UBRR0L = (unsigned char)(ubrr);
    // enable receiver, transmitter and interrupts for rx/tx
    UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0) | (1<< TXCIE0);
    // frame format: 8 bits data, 1 stop bit, no parity - these are the default settings for atmega168.
    // no change needed
    // could be changed here: //(0<<UPM00) not tested
    // UCSR0C = (1<<UCSZ00) | (1<<UCSZ01) | (0<<UPM00) | (0<<UPM01);
  
}

void USART_transmit(char c)
{
    // the commented out test if we are ready to send should work too
    //while ((UCSR0A & (1 << UDRE0)) == 0) {};
    while ( !(UCSR0A & (1<<UDRE0)) ) {}
    UDR0 = c;
}



//char char_array[] = {'a','b','c','\r','\n',0x00}; 


/*void send_string(char s[])
{
    int i =0;

    while (s[i] != 0x00) {
        USART_transmit(s[i]);
        i++;
    }
}*/


/*
 * turn on led1 and led2, wait 200ms, turn them off - do this three times
 * looks like a flashing led
 */
void flash_leds(void) {
    for (int n=0; n<3; n++) {
        PORTB |= (1 << LED1); // Turn on LED1
        PORTB |= (1 << LED2); // Turn on LED2
        _delay_ms(200);
        PORTB &= ~(1 << LED1); // Turn off LED1
        PORTB &= ~(1 << LED2); // Turn off LED2
        _delay_ms(200);
    }
}










int count = 0, a = 0;
float korrekturfaktor = 1; //hier anpassen für Abgleich (z.b 0.99974)
int ztmp = 0;
unsigned long freq = 0;
char anz[20];
volatile int s=0;
volatile unsigned short z=0;



/*********************************
Timer 0 und 2 Interruptroutinen
**********************************/


// Trigger every 8ms: (16Mhz/1024/125)
ISR(TIMER2_COMPA_vect) {
    s++;
}

// overflow counter 0
ISR(TIMER0_OVF_vect) {
    z++;
    // reset the overflow flag
    TIFR0 = (1<<TOV0);
}


// this is the interrupt service routine for receiving (its named differently on atmega32 for example)
ISR(USART_RX_vect)
{
    data = UDR0;
    if (data == 'h') {
        PORTB |= (1 << LED1); // Turn on LED1
        PORTB &= ~(1 << LED2); // Turn off LED2
    }
    else if (data == 'z') {
        PORTB |= (1 << LED2); // Turn on LED2
        PORTB &= ~(1 << LED1); // Turn off LED1
    }
    // the terminal app terminates each string with '\r\n' - the windows way of a newline
    // (linux only uses '\n')
    // so, if we dont skip '\n' and '\r' here and send z led1 will go on for some microseconds? or shorter
    // - you wont see led 1 going on.
    // because after the code read the z it will immediately receive the next character, which is a '\r'
    // and the leds will blink. same for '\n'
    else if (data == '\n') {
        // do nothing
    }
    else if (data == '\r') {
        // do nothing
    }
    else {
        //send_string(data);
        flash_leds();
    }
}


// same as above for transfer
ISR(USART_TX_vect)
{
    data = 0;
    PORTB &= ~(1 << LED1); // Turn off LED1
    PORTB |= (1 << LED2); // Turn on LED2
}













int main(void)
{
   
    DDRB |= (1 << LED1) | (1 << LED2);
    // led test
    // turn on both leds (LEDx is defined at the start of the code) to see if we did setup the 
    // ports/pins correctly and if they are really connected in the circuit
    // turn them off 3 seconds later
    // note: if you compiled your code with F_CPU=8000000 but the chip is really running with a 16Mhz Crystal,
    // they will not stay on for 3 seconds....they will go out earlier.

    PORTB |= (1 << LED1); // Turn on LED1
    PORTB |= (1 << LED2); // Turn on LED2
    _delay_ms(3000);
    PORTB &= ~(1 << LED1); // Turn off LED1
    PORTB &= ~(1 << LED2); // Turn off LED2


    
    TCCR2A |= (1<<WGM21); // CTC Mode Aktivierung Timer2
    TCCR2A |= (1<<COM2A0) | (1<<COM2A1); // set OCR Flag bei "Compare Match"
    TCCR0B |= (1<<CS02) | (1<<CS01) | (1<<CS00); //  Ext Flanke Interrupt (T0)
    TCCR2B |= (1<<CS22) | (1<<CS21) | (1<<CS20); //  Prescaler Timer2 auf 1024 setzen
    OCR2A  |= 124; // Output Compare register Timer2 auf 124 (für Loop 0-124 => 125)
    TIMSK2 |= (1<<OCIE2A); // Enable comp match flag interrupt Timer 2 
    TIMSK2 |= (1<<TOIE0); // Enable overflow flag interrupt Timer 0


    sei();

    USART_Init(MYUBRR);
    _delay_ms(10);




      
    while(1){   // 125 * 8ms = 1s, 8ms weil die isr so oft auslöst          
        if (s==125){ // "Zähltor": Abarbeitung jede Sekunde (16MHz/1024/125/125)
            count = TCNT0;
            s=0;
            ztmp = z;
            z= 0;
            TCNT0 = 0;
            freq = 0.5+((256UL*ztmp + count)*korrekturfaktor); //siehe Bemerkung unten

        // notwendig wenn RX nicht aktiviert ist?
        //while ((UCSR0A & (1 << RXC0)) == 0) {}; // Do nothing until data have been received and is ready to be read from UDR
        //ReceivedByte = UDR0; // Fetch the received byte value into the variable "ByteReceived"

        // zum testen a zurück senden
        while ((UCSR0A & (1 << UDRE0)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
        UDR0 = freq; // Echo back the received byte back to the computer

	    }
    }
}


Create a new paste based on this one


Comments: