Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <avr/io.h>
- #include <avr/eeprom.h>
- #include <avr/interrupt.h>
- #include <avr/sleep.h>
- #include <stdbool.h>
- #include <string.h>
- #define F_CPU 4000000L
- #define baudrate 9600L
- #define bauddivider (F_CPU/(16*baudrate)-1)
- #define HI(x) ((x)>>8)
- #define LO(x) ((x)& 0xFF)
- #define PACKET_BEGIN '#'
- #define COMMAND_QUERY 'Q'
- #define COMMAND_SET 'S'
- #define RESPONSE 'R'
- #define IMPULSE 'I'
- #define COUNTER_0 '0'
- #define COUNTER_1 '1'
- #define COUNTER_ALL 'A'
- #define BUF_SIZE 64 //размер буфера обязательно равен степени двойки!
- #define BUF_MASK (BUF_SIZE-1)
- #define read_eeprom(address, value_p, length) eeprom_read_block ((void*)&value_p, (const void*)address, length)
- #define write_eeprom(address, value_p, length) eeprom_write_block ((const void*)&value_p, (void*)address, length)
- typedef struct
- {
- uint16_t num_write;
- uint32_t counter[2];
- } data_t;
- typedef struct
- {
- uint8_t data[14];
- uint8_t num_data;
- } rxdata_t;
- data_t data;
- rxdata_t rx_buffer;
- bool flag_counter[2] = {0, 0}; // флаг срабатывания прерывания
- uint16_t tick[2] = {0, 0}; // счётчик защиты от дребезга
- uint8_t plus[2] = {10, 10}; // цена одного имульса
- uint16_t delay[2] = {5000, 5000}; // задержка для счётчика защиты от дребезга
- bool flag_save = false; // флаг записи в память
- uint16_t address = 0; // адрес записи в память
- uint8_t idxIN = 0;
- uint8_t idxOUT = 0;
- uint8_t serial_buffer[BUF_SIZE];
- enum KA_STATE { // Возможные состояния разборщика
- WAITING_AMPERSAND, // ожидание начала пакета
- WAITING_COMMAND, // ожидание команды
- WAITING_NUMBER, // ожидание номера счётчика
- WAITING_DATA // ожидание данных
- };
- enum KA_STATE state = WAITING_AMPERSAND;
- //обработка прерываний INT0
- SIGNAL(INT0_vect) {
- cli();
- flag_counter[0] = true;
- sei();
- }
- //обработка прерываний INT1
- SIGNAL(INT1_vect) {
- cli();
- flag_counter[1] = true;
- sei();
- }
- uint8_t read_buffer() {
- uint8_t value = 0;
- if (idxIN != idxOUT)
- {
- value = serial_buffer[idxOUT++];
- idxOUT &= BUF_MASK;
- }
- return value;
- }
- uint8_t buffer_available() {
- return (idxIN - idxOUT) & BUF_MASK;
- }
- // обработка прерываний UART RX
- ISR(USART0_RX_vect) {
- idxOUT &= BUF_MASK;
- if (buffer_available() < (BUF_SIZE - 1)) {
- serial_buffer[idxIN++] = UDR;
- idxIN &= BUF_MASK;
- }
- }
- void settings() {
- // Настройка пинов на вход
- DDRD = (0<<PD2)|(0<<PD3);
- PORTD = (1<<PD2)|(1<<PD3);
- // Настройка UART
- UBRRL = LO(bauddivider);
- UBRRH = HI(bauddivider);
- UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
- UCSRC = (3<<UCSZ0);
- // Настройка прерывания
- GIMSK = (1<<INT0)|(1<<INT1);
- MCUCR = (1<<ISC01)|(1<<ISC00)|(1<<ISC11)|(1<<ISC10);
- // Отключение компаратора
- ACSR = (1<<ACD);
- // Отключим ненужную перефирию
- PRR = (1<<PRTIM1)|(1<<PRTIM0)|(1<<PRUSI);
- sei();
- }
- // Чтение значений счётчика из EEPROM
- void read_data() {
- while(address < 250) {
- read_eeprom(address, data, sizeof(data));
- if (data.num_write != 65534)
- break;
- else
- address += sizeof(data);
- }
- if (data.num_write == 65535)
- {
- data.num_write = 0;
- data.counter[0] = 0;
- data.counter[1] = 0;
- }
- }
- // Запись значений счётчика в EEPROM
- void write_data() {
- data.num_write++;
- write_eeprom(address, data, sizeof(data));
- if (data.num_write >= 65534)
- {
- address += sizeof(data);
- data.num_write = 1;
- write_eeprom(address, data, sizeof(data));
- }
- }
- void UARTSend(uint8_t data) {
- while(!(UCSRA & (1<<UDRE)));
- UDR = data;
- }
- void UART_Send_str(uint8_t *data) {
- while (*data)
- UARTSend(*data++);
- UARTSend(0x0d);
- UARTSend(0x0a);
- }
- void int2ascii(uint8_t *data, uint8_t start, uint32_t counter) {
- uint8_t i, iNumbersCount = 0;
- uint32_t iTmpNum;
- iTmpNum = counter;
- while(iTmpNum){
- iTmpNum/=10;
- iNumbersCount++;
- }
- iTmpNum = counter;
- data += start + 10;
- for (i = 0; i < 10; i++){
- if (iNumbersCount)
- {
- *data = (char)((iTmpNum%10)|48);
- iTmpNum /= 10;
- iNumbersCount--;
- }
- else
- {
- *data = (char)(0|48);
- }
- data--;
- }
- }
- void crc(uint8_t *data, uint8_t start, uint8_t end, uint8_t *hi, uint8_t *lo ) {
- uint8_t c, i, sum = 0;
- data += start;
- for (i = start; i <= end; i++)
- {
- sum += *data++;
- }
- c = (sum & 0xf0) >> 4;
- *hi = c > 9 ? c + 0x37 : c + 0x30;
- c = (sum & 0x0f);
- *lo = c > 9 ? c + 0x37 : c + 0x30;
- }
- void UART_send_all() {
- uint8_t pack_all[26];
- pack_all[0] = 0x7e;
- pack_all[1] = 0x52;
- pack_all[2] = 0x41;
- int2ascii(pack_all, 2, data.counter[0]);
- int2ascii(pack_all, 12, data.counter[1]);
- crc(pack_all, 1, 22, &pack_all[23], &pack_all[24]);
- pack_all[25] = 0x00;
- UART_Send_str(pack_all);
- }
- void UART_Send_counter(uint8_t cnt, uint8_t type) {
- uint8_t pack[16];
- pack[0] = 0x7e;
- pack[1] = type; //0x49;
- pack[2] = (char)(cnt|48);
- int2ascii(pack, 2, data.counter[cnt]);
- crc(pack, 1, 12, &pack[13], &pack[14]);
- pack[15] = 0x00;
- UART_Send_str(pack);
- }
- void clear_buffer() {
- rx_buffer.num_data = 2;
- memset(rx_buffer.data, 0, sizeof(rx_buffer.data));
- }
- void prepare_data() {
- uint32_t result = 0;
- uint8_t i, j, hi, lo;
- for (i = 2; i < 12; i++)
- {
- result *= 10;
- j = rx_buffer.data[i] - 48;
- if (j > 9)
- {
- return;
- }
- result += j;
- }
- crc(rx_buffer.data, 0, 11, &hi, &lo);
- if (rx_buffer.data[12] != hi || rx_buffer.data[13] != lo)
- {
- UART_Send_counter(rx_buffer.data[1] - 48, RESPONSE);
- }
- else
- {
- data.counter[rx_buffer.data[1] - 48] = result;
- flag_save = true;
- UART_Send_counter(rx_buffer.data[1] - 48, RESPONSE);
- }
- }
- void prepare_serial(uint8_t rx_data) {
- switch (state)
- {
- case WAITING_AMPERSAND:
- if (rx_data == PACKET_BEGIN)
- {
- clear_buffer();
- state = WAITING_COMMAND;
- }
- break;
- case WAITING_COMMAND:
- rx_buffer.data[0] = rx_data;
- switch (rx_data)
- {
- case COMMAND_QUERY:
- state = WAITING_NUMBER;
- break;
- case COMMAND_SET:
- state = WAITING_NUMBER;
- break;
- default:
- state = WAITING_AMPERSAND;
- break;
- }
- break;
- case WAITING_NUMBER:
- rx_buffer.data[1] = rx_data;
- switch (rx_data)
- {
- case COUNTER_0:
- if (rx_buffer.data[0] == COMMAND_QUERY)
- {
- UART_Send_counter(0, RESPONSE);
- state = WAITING_AMPERSAND;
- }
- else
- {
- state = WAITING_DATA;
- }
- break;
- case COUNTER_1:
- if (rx_buffer.data[0] == COMMAND_QUERY)
- {
- UART_Send_counter(1, RESPONSE);
- state = WAITING_AMPERSAND;
- }
- else
- {
- state = WAITING_DATA;
- }
- break;
- case COUNTER_ALL:
- if (rx_buffer.data[0] != COMMAND_SET)
- {
- UART_send_all();
- }
- state = WAITING_AMPERSAND;
- break;
- default:
- state = WAITING_AMPERSAND;
- break;
- }
- break;
- case WAITING_DATA:
- if (rx_buffer.num_data == 14)
- {
- if (rx_data == 0x0d)
- {
- prepare_data();
- }
- state = WAITING_AMPERSAND;
- }
- else
- {
- rx_buffer.data[rx_buffer.num_data] = rx_data;
- rx_buffer.num_data++;
- }
- break;
- }
- }
- void check_int(uint8_t cnt) {
- if (flag_counter[cnt])
- {
- tick[cnt]++;
- if (tick[cnt] > delay[cnt])
- {
- if ((cnt == 0 && !(PIND & (1<<PD2))) || (cnt == 1 && !(PIND & (1<<PD3))))
- {
- flag_counter[cnt] = false;
- tick[cnt] = 0;
- return;
- }
- data.counter[cnt] += plus[cnt];
- flag_counter[cnt] = false;
- flag_save = true;
- tick[cnt] = 0;
- UART_Send_counter(cnt, IMPULSE);
- }
- }
- }
- int main(void)
- {
- settings();
- read_data();
- while (1)
- {
- check_int(0);
- check_int(1);
- if (buffer_available())
- {
- prepare_serial(read_buffer());
- }
- if (flag_save)
- {
- write_data();
- flag_save = false;
- }
- if (!flag_counter[0] && !flag_counter[1] && !buffer_available())
- {
- set_sleep_mode(SLEEP_MODE_IDLE);
- cli();
- sleep_enable(); // разрешаем сон
- sei();
- sleep_cpu(); // спать!
- sleep_disable();
- sei();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement