Перейти к содержанию
    

Ruffian

Участник
  • Постов

    19
  • Зарегистрирован

  • Посещение

Репутация

0 Обычный

Информация о Ruffian

  • Звание
    Участник
    Участник
  1. Дело не в том, как посчитать длительность или период. Проблема в том, что прерывание INPUT CAPTURE не происходит вообще. Если бы оно происходило и вызывалась функция обработки прерывания, я бы там уже разобрался бы, что и как подсчитать. У меня заряжены два прерывания: TIMER1_CAPT_vect и TIMER1_OVF_vect. По переполнению TIMER1_OVF_vect исправно срабатывает, а TIMER1_CAPT_vect не происходит. Прерывания настроены так: DDRB = 0;// ICP pin as input which is pin 0 on port B/ sei();//enable global interrupt //setting up Timer control register 1 //TOP VALUE IS 0XFFFF; (NORMAL MODE) TCCR1A = 0; TCCR1B = 0; //SETS PRESCALER ON 1 TCCR1B |= (1<<CS10); TCCR1B &= ~(1<<CS11) & ~(1<<CS12); // Enable Input noise canceller and capture time on rising edge TCCR1B |= (1<<ICES1)| (1<<ICNC1); //| (1<<ICNC1) TIMSK = 0; TIMSK |= (1<<TICIE1); //Enable Input Capture Interrupt TIMSK |= (1<<TOIE1); //Enable timer overflow interrupt TIFR = _BV(ICF1) | _BV(TOV1); может ещё какие флаги не установлены? В даташите вроде всё прочитал, больше никаких управляющих регистров не задействуется.
  2. К сожалению, не удается. Даже период. Сделал иначе: подаю сигнал на INT0 и его же через инвертор на INT1. В обработчике INT0 обнуляю таймер/счётчик, в обработчике INT1 останавливаю таймер, снимаю с него количество тиков, сохраняю их и перезапуск таймера. Правда используется два входа прерывания.
  3. Я конечно тупой, но не настолько :rolleyes: чтобы об этом не думать. Тактовая процика 8МГц. Измеряемые импульсы - меандр частотой около 10 КГц. Какая бы частота не была, прерывание должно срабатывать при перепадах на РВ0/РВ1. Если я правильно понял суть input capture.
  4. Да, очепятка. Правда это ничего не меняет. Прерывание срабатывает только раз
  5. Нашёл пример, перевел его с AVRStudio на mikroc. Работать отказывается. Весь вечер просидел с ним. Думаю, может ошибся когда переводил, взял оригинальный код и собрал в AVRStudio. #include <avr/io.h> #include <avr/interrupt.h> #include <math.h> // Input: Square wave on ICP PIN // This program determines the pulse width of a square wave and represents that pulse width //in a certain form in port D double overflow_counter, rising_edge, falling_edge, pulse_width; double TOP = 65535; //This interrupt service routine calculates the pulse width of a square wave on the ICP pin //and displays that in a certain form on PORT D ISR(TIMER1_CAPT_vect){ if (PORTA == 0xAA) PORTA = 0x55; else PORTA == 0xAA; // If ICP pin is set, there was a rising edge else if its low there must have been a falling edge / if (bit_is_set(PINB,1)){ rising_edge = ICR1; TCCR1B &= ~(1<<ICES1); //Capture now on falling edge overflow_counter = 0; } else{ falling_edge = ICR1; TCCR1B |= (1<<ICES1);//Capture now on rising edge pulse_width =falling_edge - rising_edge + TOP*overflow_counter; //Test to see if correct pulse width being calculated //if pulse width is greater than 35 than PD2 goes high otherwise PD3 IS HIGH if (pulse_width>35){ PORTD |= (1<<PD2); PORTD &= ~(1<<PD3); } else{ PORTD |= (1<<PD3); PORTD &= ~(1<<PD2); } } } ISR(TIMER1_OVF_vect){ overflow_counter++; //increment counter when overflow occurs } int main(void){ DDRB = 0;// ICP pin as input which is pin 0 on port B/ DDRD = 0XFF; // ALL PINS on port D are set as output. DDRA = 0xFF; PORTA = 0xAA; sei();//enable global interrupt //setting up Timer control register 1 //TOP VALUE IS 0XFFFF; (NORMAL MODE) TCCR1A = 0; TCCR1B = 0; //SETS PRESCALER ON 1 TCCR1B |= (1<<CS10); TCCR1B &= ~(1<<CS11) & ~(1<<CS12); // Enable Input noise canceller and capture time on rising edge TCCR1B |= (1<<ICES1) | (1<<ICNC1); TIMSK = 0; TIMSK |= (1<<TICIE1); //Enable Input Capture Interrupt TIMSK |= (1<<TOIE1); //Enable timer overflow interrupt while(1){} } Проект настроен на 8 МГц, Атмега16. В оригинале примера сигнал читался с PB0, хотя для Timer1 должен быть вход PB1. PB0 это для Timer0. Пробовал и так и так. В конечном счёте тупо взял и запараллелил оба входа, чтобы не гадать. Счётчик работает, прерывание TIMER1_OVF_vect срабатывает исправно, а прерывание TIMER1_CAPT_vect срабатывает только один раз, когда запускается main. И больше не вызывается. Независимо от состояния порта В. В чём прикол - не могу понять :blink:
  6. Нужно ловить два сигнала от датчиков (для простоты прямоугольные). Первый сигнал нужно измерить его длительность. Для второго сигнала просто считать количество (при каждом импульсе инкремент некоей переменной). Решил повесить эти два сигнала на INT0 и INT1. Но как разрулить - не пойму. Если по INT0 начинать считать длительность, то для этого нужен ещё и таймер. Значит третье прерывание добавляется. А что будет, если придет прерывание INT1? В общем каша образовалась. Может проще сделать вообще без прерываний, тупо в цикле опрашивать порт и смотреть, появились импульсы или нет и реагировать, если они появились? Что посоветуете?
  7. Ну это вторая попытка что-нибудь сделать в протеусе. Первую виртуальную конструкцию тоже написал, отлаживая в протеусе, затем отослал прошивку со схемой человеку, он её залил в реальную конструкцию и конструкция работает. Поэтому как-то доверял протеусу, вроде серьёзная программа. Если самому записывать в 24с04 и затем считывать записанное, то всё работает. Как минимум в пределах одного банка точно. А если протеус фтопку, то как отлаживать? В пошаговом режиме с осциллографом? Много не наладишь так
  8. Да, в протеусе для 24с04 можно указать начальные данные путём выбора какой-нибудь прошивки. Есть такой пункт в свойствах 24с04: Initial contents jf memory. Я указал ему реальную прошивку от чипа scx-4200.bin
  9. По даташиту адресация идет так: старшие 4 бита - фиксированные 1010, далее два бита - чипселект (выводы А1 и А2 у 24с04). Следующий бит - выбор одного из двух банков (которые по 256 байт). Последний бит - операция чтения или записи (1/0). Вот хочу я прочитать первую из 512 ячеек памяти. В прошивке там по этому адресу записано 0х43. Выбираю тот банк, который соответствует 0 в предпоследнем бите TWI_Start(); TWI_Write(0xA0); //выбрать первый банк TWI_Write(0); // выбрать нулевую ячейку банка TWI_Start(); TWI_Write(0xA1); // выбор операции чтения PORTA = TWI_Read(0u); // собственно само чтение TWI_Stop(); // issue TWI stop signal eepromData = PORTA; RS_Send_Char(eepromData); Вместо 0х43 возвращается 0хFF. Пробую посмотреть в другом банке, может там искомое найдётся: TWI_Start(); TWI_Write(0xA2); //выбрать второй банк TWI_Write(0); // выбрать нулевую ячейку банка TWI_Start(); TWI_Write(0xA3); // выбор операции чтения PORTA = TWI_Read(0u); // собственно само чтение TWI_Stop(); // issue TWI stop signal eepromData = PORTA; RS_Send_Char(eepromData); Возвращается 0хА3 вместо 0х43 В чём ошибка?
  10. Чтение по TWI

    Добрый день. Помогите разобраться с простейшим примером работы с TWI void RS_Send_Char(char c); void RS_Send_Text (char *text); char eepromData; void main(){ DDRA = 0xFF; // configure PORTA as output UART1_Init(9600); Delay_ms(200); RS_Send_Text("test"); // часть 1 TWI_Init(100000); // initialize TWI communication TWI_Start(); // issue TWI start signal TWI_Write(0xA2); // send byte via TWI (device address + W) TWI_Write(2); // send byte (address of EEPROM location) TWI_Write(0xAA); // send data (data to be written) TWI_Stop(); // issue TWI stop signal Delay_100ms(); // часть 2 TWI_Start(); // issue TWI start signal TWI_Write(0xA2); // send byte via TWI (device address + W) TWI_Write(2); // send byte (data address) TWI_Start(); // issue TWI signal repeated start TWI_Write(0xA3); // send byte (device address + R) PORTA = TWI_Read(0u); // read data (NO acknowledge) TWI_Stop(); // issue TWI stop signal eepromData = PORTA; RS_Send_Char(eepromData); Delay_100ms(); // часть 3 TWI_Start(); // issue TWI start signal TWI_Write(0xA2); // send byte via TWI (device address + W) TWI_Write(1); // send byte (data address) TWI_Start(); // issue TWI signal repeated start TWI_Write(0xA3); // send byte (device address + R) PORTA = TWI_Read(0u); // read data (NO acknowledge) TWI_Stop(); // issue TWI stop signal eepromData = PORTA; RS_Send_Char(eepromData); } //вывод в терминал void RS_Send_Char(char c){ while ( !(UCSRA & 0b00100000) ); //waiting for ready UDR = c; } void RS_Send_Text (char *text){ while ( *text ){ RS_Send_Char (*text); text ++; } } Схема простейшая: Atmega16 и 24c04. У 24с04 ножки А1 и А2 сидят на общем проводе. В первой части записывается число АА в память, во второй части оно успешно считывается обратно из памяти, а в третьей я пытаюсь прочитать какую-нибудь другую ячейку, но результат чтения явно не тот, что должен быть. 1. Непонятно, почему именно TWI_Write(0xA2), что за адрес 0хА2, и почему не 159 или 1? Исходя из чего? Я не вижу связи числа 0хА2 с состоянием адресных ножек 24с04. 2. TWI_Write(2); Здесь 2 - это номер ячейки памяти в 24с04? Если так, то почему при чтении из другой ячейки TWI_Write(1); читается не то, что прописано в этой ячейке 24с04, а число А3? При этом в протеусе 24с04 изначально инициализирована реальной прошивкой, в которой А3 нет ни в одной ячейке. Какую ячейку не считывай (кроме ячейки 2), получаю число А3. Если вместо TWI_Write(0xA3); сделать например TWI_Write(0x66); - будет со всех ячеек считываться 66.
  11. что-то я не найду в проекте свойства "размер стека". Есть только выбор девайса и частоты генератора.
  12. .lss в папке проекта не обнаружил. Есть .lst - там ассемблерный листинг. В общем всю папку проекта прицепил. И протеусовскую схему, и простой рисунок схемы в формате png. Если закомментировать все UDR=0 то ошибка начнет появляться. terminal.zip
  13. В общем при передаче в терминал обнаружилась ошибка. Делаю так: В протеусе подключаю к МК два устройства: 1. Элемент VirtualTerminal 2. Элемент компорта COMPIM. Этот COMPIM связываю со встроенным виндовым терминалом. Запускаю симуляцию и оба терминала отображают мне такие строки: "ello From Hell" "lAA" Первый байт передачи исчез. Последний байт первой строки (l) был передан со второй строкой, а последний байт второй строки остался непереданным. Если после этого передать например "ВВВ" а затем "ССС", то в терминал придёт "АВВ" и "ВСС" После ковыряние в дебаггере обнаружил, что регистр данных UDR непосредственно перед передачей содержит последний байт предыдущей передачи. И соответственно пуляет сначала его, а затем байты текущей передачи количеством n-1. Последний байт текущей передачи остается непереданным и сидит в UDR, ожидая своей очереди до следующей передачи. Дальше сделал так: перед каждым UART1_Write принудительно стал обнулять UDR. И всё встало на свои места. В терминалах корректно отображается всё, что было передано. Но нигде не видел, чтобы принудительно надо было обнулять UDR перед передачей. Почему так, в чем проблема?
  14. Что за диагностика? Можно чуть подробнее? Debug оказался в моем случае бессилен
  15. Схема есть в архиве. Называется terminal.dsn Да, да, да !!! Точно, поставил Rx и Tx перехлестом - заработало! Ввод с терминала теперь отображается на LCD. Спасибо! Я почему-то подумал, что одноименные выводы соединить надо. Пойду смотреть как в обратную сторону из МК на терминал работает. Ещё раз спасибо!
×
×
  • Создать...