Ok so I partly fixed the problem, the else if statements were not in right order in my ISR function. Right now pushing the button just stops the program probably becouse of this fact that I didn't know about:
The Arduino Wire library is interrupt-driven, you may not use it in a interrupt routine.
Thank you for the input and also I agree with alto777 that I provided too little context. I'm providing my simplified (or maybe not so much) code below.
#include <Wire.h>
#define DIGITS_COUNT 5
#define RTC_ADDR 0x68
#define HOUR_ADDR 0x02
//Current digit position for display
uint8_t position = 0;
//Current digits array with digit number and dot point status
uint8_t display_array[DIGITS_COUNT][2];
//Position lookup table for PORT manipulation
const uint8_t position_array[DIGITS_COUNT] = {0b00000001, 0b00000010, 0b00000100, 0b01000000, 0b10000000}; //CA1,CA2,CA3,CA4,CA5
//Digit segment configuration for PORT manipulation
const uint8_t digits_array[11] = {0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110, 0b01101101, 0b01111101, 0b00000111, 0b01111111, 0b01101111, 0b00000000}; //0,1,2,3,4,5,6,7,8,9,null
ISR(TIMER1_COMPA_vect) {
display_write();
}
ISR(PCINT1_vect) {
if (!(PINC & 0b00000010) & write_mode) { //If button was pressed (detect LOW state)
rtc_write(HOUR_ADDR,1); //test
}
}
void setup() {
//Set Timer 1 to interrupt and refresh screen periodacly
TCCR1A = 0b00000000;
TCCR1B = 0b00001001; //No prescaler, CTC for OCR1A
TCNT1 = 0; //Reset initial value
TIMSK1 |= 0b00000010; //Set interrupt on compare A
OCR1A = 5000; //Display new digit every 5ms
//Set D and B pins as outputs for driving the display
DDRD = 0b11111111;
DDRB |= 0b11000111;
//Set C pin as input for switch and enable pullup resistor
DDRC &= 0b11111101;
PORTC |= 0b00000010;
//Initialize Pin Chnage Interrupts
PCICR |= 0b00000010; //Enable PCI for bank C
PCIFR |= 0b00000111; //Clear interrupt flags
PCMSK1 |= 0b00000010; //Enable PCI for PC1
//Initialize I2C communication library
Wire.begin();
//Enable external interrupts
sei();
}
void loop() {
//Set dot positions
display_array[0][1] = 0;
display_array[1][1] = 1;
display_array[2][1] = 0;
display_array[3][1] = 1;
display_array[4][1] = 0;
rtc_read(HOUR_ADDR, 0, 1);
}
//Read data from RTC and insert digits to positions in display array
void rtc_read(uint8_t address, uint8_t position1, uint8_t position2) {
uint8_t data_bcd;
uint8_t data_dec;
Wire.beginTransmission(RTC_ADDR);
Wire.write(address);
Wire.endTransmission();
Wire.requestFrom(RTC_ADDR,1);
if (Wire.available()) {
data_bcd = Wire.read();
}
data_dec = (data_bcd / 16 * 10) + (data_bcd % 16); //Convert RTS's BCD format to decimal
display_array[position1][0] = data_dec / 10; //Write most siginificant digit to position 1
if (position2 < DIGITS_COUNT) {
display_array[position2][0] = data_dec % 10; //Write least siginificant digit to position 2
}
}
//Write data to RTC
void rtc_write(uint8_t address, uint8_t value) {
Wire.beginTransmission(RTC_ADDR);
Wire.write(address);
Wire.write((value / 10*16) + (value % 10));
Wire.endTransmission();
}
//Display array function
void display_write() {
if (display_array[position][0] < 11) {
PORTB &= 0b00111000; //Reset B pins
PORTD = digits_array[display_array[position][0]]; //Set segment configuration from digits_array look-up table
PORTD |= (display_array[position][1] << PD7); //Add dot point bit status to current digit
PORTB |= position_array[position]; //Add bit corresponding to position argument from position_array look-up table
position++; //Move to next digit position
if (position == DIGITS_COUNT) { //Reset digit counter when last position is reached
position = 0;
}
}
}
Context: There is a debounced pushbuttong pulling pin PC1 to ground when pressed. I want this buttong to act as an interrupt and use write function to write some data to RTC when it's pressed. The code is in it's first stages and it's my forst big project with ATMega and I'm using it as a bare-metal MCU soldered on PCB. Banks B and D are driving the segments and cathodes of 5 digit 7-segment display. I want to ultimetly write it in pure C in Microchip Studio using only standard avr libraries.
Currently as I said pushing the button just stops the program - digits stop refreshing. If Wire library is interrupt driven is it better idea to just try to write simplified I2C communication functions from scratch?