Некорректно считывается TCNT1, ATmega168 Привет.
Проблема: неправильно считывается значение счётного регистра (TCNT1, ATmega168)
Каждые 12мс происходит прерывание по сравнению
Ожидаю увидеть значение около 12000(dec) (0x2EE0). Приходит в 4 раза больше. Сделал всё по дататашиту.
И прерывания запрещал-разрешал на момент считывания.
Привожу код:
void init(){
// порты C и D
DDRC |= 1<<DDC0 | 1<<DDC1 | 1<<DDC2 | 1<<DDC3 | 1<<DDC4;
PORTC |= 1<<PC3; // сигнал Strob в "0", D1 в "1"
PORTC &= ~(1<<STROB); // Сигналы Strob и D1
PORTC |= 1<<D1;
//PORTC |= 1<<PC4; // отладочный светодиод
DDRD &= ~(1<<DDD0 | 1<<DDD3);
DDRD |= 1<<DDD1 | 1<<DDD2;
//PORTD |= 1<<PD2; в режиме приёма PD2 = 0
//EICRA |= 1<<ISC10 | 1<<ISC11; // внешнее
//EIMSK |= 1<<INT1;
TIMSK1 |= 1<<OCIE1A | 1<<OCIE1B; // прерывание таймера1 по сравнению
// таймер
//OCR1AL = _200us;
OCR1A = _200us;
OCR1B = _12ms;
//TCCR1B |= 1<<CS10 | 1<<CS12;
//TCCR1B |= 1<<CS10 | 1<<CS11;
TCCR1B |= 1<<CS11;
// UART
UBRR0 = 7; // скорость 57600
UCSR0B |= 1<<RXEN0 | 1<<RXCIE0 | 1<<TXEN0; // разрешили прерывания по приёму и передаче
// переменные и флаги
//request[1] = RUN_IMPULSES_DIR1_DIR2; // по умолчанию работают 2 последовательности
request[0] = 0;
//request[1] = RUN_IMPULSES_DIR1_DIR2;
request[1] = RUN_IMPULSES_DIR1;
request[2] = 0;
request[3] = 0;
answer[0] = REQUEST_START;
answer[1] = 0;
answer[2] = 0;
answer[3] = 0;
answer[4] = 0;
answer[5] = 0;
answer[6] = 0;
answer[7] = 0;
answer[8] = 0;
answer[9] = 0;
answer[10] = 0;
answer[11] = 0;
answer[12] = 0;
//unsigned char answer[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
flags.form_impulse = 1;
flags.impulse_was_on_line = DIR_2;
flags.half_period_passed = 0;
flags.send_answer = 0;
flags.run_measure_dir_1 = 0;
//flag = 0;
//flag_send_answer = 0;
rx_stage = 0;
// прерывания:
SREG |= 0b10000000; // все
}
ISR(TIMER1_COMPB_vect){ // срабатывает по сравнению, через 12 мс после сброса счётного регистра
/*
cli();
TCNT1L = 0x0F;
TCNT1H = 0xF0;
sei();
*/
//cli();
answer[4] = TCNT1L;
answer[3] = TCNT1H;
//sei();
//PORTC |= 1<<PC1; // отладочный светодиод !!!! 40 мс!!
flags.run_measure_dir_1 = 0;
flags.run_measure_dir_2 = 0;
//invert_Strob_D1();
PORTC &= ~(1<<STROB); // Сигналы Strob и D1
PORTC |= 1<<D1;
if (request[1] == RUN_IMPULSES_DIR1_DIR2){
if (flags.impulse_was_on_line == DIR_2){
form_impulse(DIR_1);
//flags.run_measure_dir_1 = 1;
//TIMSK1 |= 1<<OCIE1A;
flags.impulse_was_on_line = DIR_1;
}
else
if (flags.impulse_was_on_line == DIR_1){
form_impulse(DIR_2);
//flags.run_measure_dir_1 = 1;
//TIMSK1 |= 1<<OCIE1A;
flags.impulse_was_on_line = DIR_2;
//SREG = 0;
}
}
else
if (request[1] == RUN_IMPULSES_DIR1){
if (flags.half_period_passed == 0){
form_impulse(DIR_1); // формируем спустя первые 12 мс
//flags.run_measure_dir_1 = 1;
//TIMSK1 |= 1<<OCIE1A;
flags.half_period_passed = 1;
} else {
flags.half_period_passed = 0; // через 12 мс - ещё 12 мс
}
}
else
if (request[1] == RUN_IMPULSES_DIR2){
if (flags.half_period_passed == 0){
form_impulse(DIR_2);
flags.run_measure_dir_2 = 1;
//TIMSK1 |= 1<<OCIE1A;
flags.half_period_passed = 1;
} else {
flags.half_period_passed = 0;
}
}
TCNT1H = 0;
TCNT1L = 0;
}
#include <avr\io.h>
#include <avr\interrupt.h>
#include <util\delay.h>
#include <util\crc16.h>
//#define _200us 2
//#define _12ms 87
//#define _200us 23
//#define _12ms 1382
#define _200us 182
#define _12ms 10909
//#define _12ms 5000
#define DIR_1 0
#define DIR_2 1
#define STROB PC2
#define D1 PC3
#define BEGIN 0
// запрос
#define WAITING_START 0
#define WAITING_COMMAND 1
#define WAITING_LRC_HIGH 2
#define WAITING_LRC_LOW 3
#define LAST 4
#define REQUEST_START 0x3A
#define RUN_IMPULSES_DIR1 0x01
#define RUN_IMPULSES_DIR2 0x02
#define RUN_IMPULSES_DIR1_DIR2 0x03
// ответ
#define ANSWER_START 0x3A
#define FLAG_NORM_DIR_1 0x81
#define FLAG_FAILURE_DIR_1 0x01
#define FLAG_NORM_DIR_2 0x82
#define FLAG_FAILURE_DIR_2 0x02
/* Прототипы функций */
void init(); // инициализация всего
void send_answer(); // отправка посылки из UART0
void debug();
void send_byte(unsigned char data);
//void run_time(unsigned char* time);
//void invert_Strob_D1();
void form_impulse(unsigned char line);
//unsigned short get_lrc(unsigned char *p);
unsigned short get_lrc();
void send_answer();
void measure(unsigned char line);
/* Переменные, массивы, структуры */
unsigned char rx_stage; // счётчик стадии приёма посылки
unsigned short lrc;
unsigned char request[5]; //
unsigned char answer[13]; //
//unsigned char answer[13] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char line_flag;
unsigned char debug_var;
// запрос
union{
unsigned short two_bytes;
struct{
unsigned char low;
unsigned char high;
} byte;
} request_lrc, answer_lrc;
// ответ
union{
float four_bytes;
struct{
unsigned char first_high;
unsigned char second;
unsigned char third;
unsigned char fourth_low;
} byte;
} t1, t2;
struct{
unsigned int failure_or_norm: 1; // 0 - авария, 1 - норма
unsigned int form_200us: 1;
unsigned int form_impulse: 1;
unsigned int form_12ms: 1;
unsigned int impulse_was_on_line: 1;
unsigned int half_period_passed: 1;
unsigned int send_answer: 1;
unsigned int _12ms_passed: 1;
//unsigned int send: 1;
unsigned int run_measure_dir_1: 1;
unsigned int run_measure_dir_2: 1;
} flags;
/*
Кварц 7.3728 МГц
Время такта: 1/(7.3728 * 10^6) = 0.135*10^-6 с
Время такта без предделителя: 1/(7.3728 * 10^6) = 0.135 мкс
Столько тактов нужно для формирования времени 12 мс: 12 мс / 0.138 мкс = 86956 - переполняет регистр
Время такта c учётом предделителя 1024: 1/(7.3728 * 10^6 / 1024) = 0.138 мс
Столько тактов нужно для формирования времени 12 мс: 12 мс / 0.138 мс = 87
Столько тактов нужно для формирования времени 200 мкс: 200 мкс / 0.138 мс = 1.44 = 2
Время такта c учётом предделителя 64: 1/(7.3728 * 10^6 / 64) = 8.68 мкс
Столько тактов нужно для формирования времени 12 мс: 12 мс / 8.68 мкс = 1382
Столько тактов нужно для формирования времени 200 мкс: 200 мкс / 8.68 мкс = 23
Время такта c учётом предделителя 8: 1/(7.3728 * 10^6 / 8) = 1.1 мкс
Столько тактов нужно для формирования времени 12 мс: 12 мс / 1.1 мкс = 10909
Столько тактов нужно для формирования времени 200 мкс: 200 мкс / 1.1 мкс = 182
*/