I write a code for ATmega328P(Arduino NANO). It will control a servo motor and pump using the Bluetooth module HC-10. Compiler compiles the code without mistakes, but the simulation doesn't work. The same problem happened when i call a functions without "inline" keyword. Ok but what's wrong now with ICR interrupt? I am a beginner on this way so can someone help me?
This is a code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
enum {
SERVO_MAX_RIGHT = 500,
SERVO_MAX_LEFT = 248,
SERVO_MID = 375,
BAUD = 9600,
FOSC = 16000000,
MYUBRR = FOSC/16/BAUD-1,
BUT_L = 97, // Turn left button number (ASCII)
BUT_R = 100,
BUT_M = 115,
};
struct button {
unsigned char leftOn;
unsigned char rightOn;
unsigned char moveOn;
unsigned char pressed;
} button;
static inline void portInit() {
DDRC &= ~(1<<DDC0); // Set buttons ports direction to input
DDRC &= ~(1<<DDC1);
DDRC &= ~(1<<DDC2);
PORTC |= (1<<PORTC0); // Apply 5v voltage to buttons ports
PORTC |= (1<<PORTC1);
PORTC |= (1<<PORTC2);
DDRB |= (1<<PB0); // Set output direction for Pump port pin
PORTB &= ~(1<<PB0); // Set 0V for Pump port
DDRB |= (1<<PB1); // Set output direction for Servo port pin
PORTB &= ~(1<<PB1); // Set 0V for servo port
}
static inline void timerInit() {
unsigned char sreg;
TCCR1A |= (1<<COM1A1); // Set the non-invert mode PWM
TCCR1A &= ~(1<<COM1A0);
TCCR1A &= ~(1<<WGM10); // Set the Fast PWM bit mode
TCCR1A |= (1<<WGM11);
TCCR1B |= (1<<WGM12);
TCCR1B |= (1<<WGM13);
TCCR1B |= (1<<CS10); // Set the prescaler CLKi/o/64
TCCR1B |= (1<<CS11);
TCCR1B &= ~(1<<CS12);
sreg = SREG; // Disable global interrupt flag
cli();
ICR1 = 5000; // Set the pulse width
SREG = sreg; // Restore global interrupt flag
}
static inline void uartInit(unsigned int ubrr) {
UBRR0H = (unsigned char) (ubrr>>8); // Set the BAUD rate in USART baud Rate
UBRR0L = (unsigned char)ubrr; // Registers (to low & high)
UCSR0B = 0b10011000; // Set the RX&TX&Interrupt Rx enable
UCSR0C = ~(1<<USBS0); // Set the 1 stop bit
UCSR0C = ~(1<<UCSZ02); // Set the 8 bit package settings
UCSR0C = (1<<UCSZ01);
UCSR0C = (1<<UCSZ00);
}
static inline void uart_send(char* str) {
while(*str) {
while(UCSR0A & (1<<UDRE0)) { // While UDR is ready to recieve new data
UDR0 = *str;
str++;
}
}
}
static inline void uart_boatControl(unsigned char read) {
uint8_t val;
if(read) {
val = UDR0;
switch(val) {
case BUT_L:
OCR1A = SERVO_MAX_LEFT;
break;
case BUT_R:
OCR1A = SERVO_MAX_RIGHT;
break;
case BUT_M:
PORTB = (1<<PB0);
break;
default:
OCR1A = SERVO_MID;
PORTB = ~(1<<PB0);
}
}
}
ISR(USART_RX_vect){
button.pressed = UCSR0A & (1<<RXC0);
uart_boatControl(button.pressed);
}
int main(void)
{
portInit();
timerInit();
OCR1A = SERVO_MID; // Set the Servo to midle (0 degree)
_delay_ms(500);
uartInit(MYUBRR);
while(1) {
button.leftOn = (!(PINC&(1<<PC0)));
button.rightOn = (!(PINC&(1<<PC1)));
button.moveOn = (!(PINC&(1<<PC2)));
if (button.leftOn) {
OCR1A = SERVO_MAX_LEFT;
} else if (button.rightOn) {
OCR1A = SERVO_MAX_RIGHT;
} else if (button.moveOn) {
PORTB |= (1<<PB0);
} else {
OCR1A = SERVO_MID;
PORTB &= ~(1<<PB0);
}
}
return 0;
}
I found the solution for ISR(). In my code there are no mistakes when i call the function after main() function. But when i try to find the right way to program, i did it the other way. Perhaps someone will be interested.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
enum {
SERVO_MAX_RIGHT = 655,
SERVO_MAX_LEFT = 527, // 248 default
SERVO_MID = 400,
BAUD = 9600,
FOSC = 16000000,
MYUBRR = FOSC/16/BAUD-1,
BUT_L = 97, // Turn left button number (ASCII)
BUT_R = 100,
BUT_M = 115,
};
struct butt {
unsigned char leftOn;
unsigned char rightOn;
unsigned char moveOn;
} butt;
static inline void portInit();
static inline void timerInit();
static inline void uartInit
(unsigned int ubrr);
static inline void uart_send(char* str);
static inline void uart_boatControl
(unsigned char data);
static inline void analog_boatControl(unsigned char bL,
unsigned char bR, unsigned char mv);
int main(void)
{
portInit();
timerInit();
OCR1A = SERVO_MID; // Set the Servo to midle (0 degree)
_delay_ms(500);
uartInit(MYUBRR);
PORTD &= ~(1<<PD7);
while(1) {
uart_boatControl(UDR0);
}
return 0;
}
static inline void portInit() {
DDRC &= ~(1<<DDC0); // Set buttons ports direction to input
DDRC &= ~(1<<DDC1);
DDRC &= ~(1<<DDC2);
PORTC |= (1<<PORTC0); // Apply 5v voltage to buttons ports
PORTC |= (1<<PORTC1);
PORTC |= (1<<PORTC2);
DDRB |= (1<<PB0); // Set output direction for Pump port pin
PORTB &= ~(1<<PB0); // Set 0V for Pump port
DDRB |= (1<<PB1); // Set output direction for Servo port pin
PORTB &= ~(1<<PB1); // Set 0V for servo port
DDRD |= (1<<PD7);
}
static inline void timerInit() {
unsigned char sreg;
TCCR1A |= (1<<COM1A1); // Set the non-invert mode PWM
TCCR1A &= ~(1<<COM1A0);
TCCR1A &= ~(1<<WGM10); // Set the Fast PWM bit mode
TCCR1A |= (1<<WGM11);
TCCR1B |= (1<<WGM12);
TCCR1B |= (1<<WGM13);
TCCR1B |= (1<<CS10); // Set the prescaler CLKi/o/64
TCCR1B |= (1<<CS11);
TCCR1B &= ~(1<<CS12);
sreg = SREG; // Disable global interrupt flag
cli();
ICR1 = 5000; // Set the pulse width
SREG = sreg; // Restore global interrupt flag
}
static inline void uartInit
(unsigned int ubrr) {
UBRR0H = (unsigned char) (ubrr>>8); // Set the BAUD rate in USART baud Rate
UBRR0L = (unsigned char)ubrr; // Registers (to low & high)
UCSR0B = 0b10011000; // Set the RX&TX&Interrupt Rx enable
UCSR0C &= ~(1<<USBS0); // Set the 1 stop bit
UCSR0C &= ~(1<<UCSZ02); // Set the 8 bit package settings
UCSR0C |= (1<<UCSZ01);
UCSR0C |= (1<<UCSZ00);
}
static inline void uart_send(char* str) {
while(*str) {
while(UCSR0A & (1<<UDRE0)) { // While UDR is ready to recieve new data
UDR0 = *str;
str++;
}
}
}
static inline void uart_boatControl
(unsigned char data) {
while(!(UCSR0A & (1<<RXC0))) {
};
while(UCSR0A & (1<<RXC0)) {
switch(UDR0) {
case BUT_L:
OCR1A = SERVO_MAX_LEFT;
break;
case BUT_R:
OCR1A = SERVO_MAX_RIGHT;
break;
case BUT_M:
PORTB = (1<<PB0);
break;
default:
OCR1A = SERVO_MID;
PORTB &= ~(1<<PB0);
}
}
}
static inline void analog_boatControl(unsigned char bL,
unsigned char bR, unsigned char mv) {
if (bL) {
OCR1A = SERVO_MAX_LEFT;
} else if (bR) {
OCR1A = SERVO_MAX_RIGHT;
} else if (mv) {
PORTB |= (1<<PB0);
} else {
OCR1A = SERVO_MID;
PORTB &= ~(1<<PB0);
}
}