Опытный
Профиль
Группа: Участник
Сообщений: 658
Регистрация: 25.8.2005
Репутация: нет Всего: 1
|
В продолжении темы - обнаружение фазового сдвига. Я почти написал код на си для мк atmega16. Устройство rfid читалка стандарта emmarine(em4100) (Все 5 видов модуляции) В протеусе всё работает превосходно. За исключением одного НО. Вкрадце если рассказать, то алгоритм такой. На вход мк (захват таймера1) поступает выделенная огибающая с приёмной катушки. Сначала пробуем распознать формат манчестер 64 периода на 1 бит, потом манчестер 32, далее бифаза 64, потом бифаза 32. И наконец PSK 16, который не работает. В первых 4 вариантах я ловил прерывания, отсчитывал временные интервалы и если они совпадали с условием, то я ставил флаг, который пропускается в основном цикле программы. Я старался в прерывании сделать как можно меньше действий, а саму обработку - в основном цикле. Так вот, когда в блоке прерываний было ясно что принята либо 1 либо 0, далее проваливаемся в основной цикл программы, где идёт обработка. То есть сначала считаем заголовок (9 единиц), потом когда пошли данные считаем CRC, потом высчитываем СRC. И если биты чётности совападают - идём дальше. А если нет, то программа задействует ф-ию another_format и пробует заново считать код уже в другом формате. Фишка в том, что в первых 4 случаях 1 бит равнялся 64 или 32 периода таймера. И поэтому обработка в основном цикле спокойно успевала закончится. А вот когда я пробую также сделать с PSK 16, то обработка просто не успевает пройти, потому как через 2 тика таймера уже следующее прерывание. Для наглядности что такое PSK 16 (на вход мк поступает Modulator control) . Так вот подскажите пожалуйста. Сейчас я по мере поступления данных делаю обработку (вычисляю и сравниваю CRC). Может сделать так: Сначала просто и быстро набить массив data[64] данными (в стандарте em4100 - 64 бита данных), а потом уже спокойно расковыривать этот массив и вычислять CRC? Хотя тогда замедлится принятие решения о том что это другой формат например... Весь код на данный момент Код | #define F_CPU 16000000
#include <avr/io.h> #include <string.h> #include <avr/interrupt.h> #include <stdlib.h> #include <stdio.h> #include <util/delay.h>
volatile unsigned char edge_counter; volatile unsigned char interrupt_counter; unsigned char bit_counter; unsigned char byte_counter; unsigned char crc_counter; unsigned char RFID_buffer[6]; volatile unsigned char edge_min_false = 62; volatile unsigned char edge_min_true = 126; volatile unsigned char edge_max_true = 126; volatile unsigned char system; //system// //bit 3 - 0=заход в прерывание 1-й раз 1=заход в прерывание последующие разы //bit 1 - если 0, то принимаем заголовок, если 1, то заголовок приняли и далее идут данные //bit 0 - 1-разрешаем заход в основной цикл программы для обработки //bit 2 - установка этого бита означает, что приняты все биты всключая стоповый и далее следует сравнить чётность столбов и принять решение о распозновании метки. //bit 4 - бит для проверки чётности CRC. 1 - нечётно, 0 - чётно. //bit 5 - бит распознования метки. Если 1 - метка распознана. Если 0 - нет. Распознование - сравнение CRC по столбам. //bit 6 - Данные volatile unsigned char format = 0x1; //format// //bit 0 - EM4100A6 //bit 1 - EM4100A5 //bit 2 - EM4100B6 //bit 3 - EM4100B5 //bit 4 - EM4100C4
//Macros###################################################################### #define SetBit(reg, bit) reg |= (1 << bit) #define ClearBit(reg, bit) reg &= ~(1 << bit) #define BitIsSet(reg, bit) ((reg & (1 << bit)) != 0) #define BitIsClear(reg, bit) ((reg & (1 << bit)) == 0) #define ShiftBitRight(reg) reg >>= 1 #define CalculateCRC(reg, bit) reg ^= (1 << bit) //############################################################################
//Functions################################################################### void USART_SendChar(unsigned char sym){ while(!(UCSRA & (1 << UDRE))); UDR = sym; }
void Another_Format(){ if(TCCR1B == 0xC3){TCCR1B = 0x83;}//Если последний принятый бит перед вкидыванием в anotherformat был 0, то надо перенастроить прерывание сначала по спаду, потом по росту. иначе не будет работать interrupt_counter = 0; bit_counter = 0; byte_counter = 0; crc_counter = 0; RFID_buffer[6] = 0; system = 0; edge_counter = 0; format <<= 1; if(format == 0x2){ edge_min_false = 30; edge_min_true = 62; } if(format == 0x4){ edge_min_true = 62; edge_max_true = 126; } if(format == 0x8){ edge_min_true = 30; edge_max_true = 62; } if(format == 0x20){ format = 0x1; edge_min_false = 62; edge_min_true = 126; } //-------------test in proteus------------- PORTD ^= (1 << 5); TCCR2 &= ~(1 << COM20); _delay_ms(1); TCCR2 |= (1 << COM20); if(format == 0x2 || format == 0x1){TCCR1B = 0xC3;} //По наростающему фронту. if(format == 0x4 || format == 0x8 || format == 0x10){TCCR1B = 0x83;} //По спадающему фронту. //----------------------------------------- } //###########################################################################
ISR(TIMER1_CAPT_vect){ if((format == 0x1) || (format == 0x2)){ if(BitIsClear(system, 3)){//заходим в прерывание первый раз, следующий уже не заходим сюда PORTC |= (1 << 0);//////////////// asm("nop");/////////////////////// PORTC &= ~(1 << 0);/////////////// TCNT1 = 0x00; TIFR |= 0x20; if(TCCR1B == 0xC3){//Если прерывание настроено на активный фронт TCCR1B = 0x83;//то перенастраиваем его на активный спад, т.к. в следующий раз будет полюбасу спад SetBit(system, 0); SetBit(system, 6); }else{ TCCR1B = 0xC3; SetBit(system, 0); ClearBit(system, 6); } SetBit(system, 3); }else{ edge_counter = ICR1;//записываем в переменную сколько оттикал таймер. if(edge_counter >= edge_min_false && edge_counter <= (edge_min_false + 4)){//если таймер оттикал 62-66 тиков, то это на границе битов и в расчёт не берётся //TIFR |= 0x20;//принудительно сбрасываем флаг прерываний if(TCCR1B == 0xC3){TCCR1B = 0x83;}else{TCCR1B = 0xC3;}//меняем условие прерывания для следующего фронта }else if(edge_counter >= edge_min_true && edge_counter <= (edge_min_true + 4)){//если таймер оттикал 126-130 тиков, то это середина бита. Это и есть нужный фронт TCNT1 = 0x00;//Обнуляем счётчик TIFR |= 0x20; if(TCCR1B == 0xC3){//если прерывание было настроено по активному фронту, то TCCR1B = 0x83; SetBit(system, 0); SetBit(system, 6); //приняли 1 }else{ TCCR1B = 0xC3; SetBit(system, 0); ClearBit(system, 6); //приняли 0 } PORTC |= (1 << 0);//////////////// asm("nop");/////////////////////// PORTC &= ~(1 << 0);/////////////// } } } if(format == 0x4 || format == 0x8){ //Если формат biphase 64 или 32 if(BitIsClear(system, 3)){ //Если 0 то это первый заход в прерывание. Тут данные не собираем, а начинаем отсчёт TCNT1 = 0x00; TIFR |= 0x20; if(TCCR1B == 0x83){ TCCR1B = 0xC3; }else{ TCCR1B = 0x83; } SetBit(system, 3); }else{ //Последующие заходы в прерывание edge_counter = ICR1;//записываем в переменную сколько оттикал таймер. TCNT1 = 0x00; TIFR = 0x20; if(edge_counter >= edge_max_true && edge_counter <= (edge_max_true + 4)){//Если длина бита = 64 цикла. прерывание сработало вконце бита(количество тиков между прерываниями) то это 1 if(TCCR1B == 0xC3){TCCR1B = 0x83;}else{TCCR1B = 0xC3;} SetBit(system, 0); SetBit(system, 6); //приняли 1 PORTC |= (1 << 0);//////////////// asm("nop");/////////////////////// PORTC &= ~(1 << 0);/////////////// }else if(edge_counter >= (edge_min_true) && edge_counter <= (edge_min_true + 4)){//Если в середине бита сработало прерывание, то это 0 и следующее прерывание игнорим if(TCCR1B == 0xC3){TCCR1B = 0x83;}else{TCCR1B = 0xC3;} SetBit(system, 0); ClearBit(system, 6); //приняли 0 ClearBit(system, 3);//Игнорим следующее прерывание PORTC |= (1 << 0);//////////////// asm("nop");/////////////////////// PORTC &= ~(1 << 0);/////////////// } } } if(format == 0x10){//Если формат PSK 16 if(BitIsClear(system, 3)){ //Если 0 то это первый заход в прерывание. Тут данные не собираем, а начинаем отсчёт TCNT1 = 0x00; TIFR |= 0x20; if(TCCR1B == 0x83){TCCR1B = 0xC3;}else{TCCR1B = 0x83;} SetBit(system, 3); SetBit(system, 0); SetBit(system, 6); }else{ TCNT1 = 0x00; TIFR = 0x20; if(TCCR1B == 0x83){TCCR1B = 0xC3;}else{TCCR1B = 0x83;} if(interrupt_counter == 16){ edge_counter = ICR1;//записываем в переменную сколько оттикал таймер. if(edge_counter <= 3){ SetBit(system, 0); SetBit(system, 6); }else if(edge_counter > 3){ SetBit(system, 0); ClearBit(system, 6); } } } interrupt_counter++; } }
int main(void){ SetBit(DDRC, 0);//////////////////////////// ClearBit(PORTC, 0);///////////////////////// SetBit(DDRD, 5);//////////////////////////// ClearBit(PORTD, 5);///////////////////////// SetBit(DDRD, 7); ClearBit(DDRD, 6); SetBit(PORTD, 6); OCR2 = 63; TCCR2 = 0x19; TCCR1A = 0x00; TCCR1B = 0xC3; TCNT1 = 0x00; ICR1 = 0x00; TIMSK = 0x20; UCSRA = 0x00; UCSRB = 0x18; UCSRC = 0x86; UBRRH = 0x00; UBRRL = 0x8; asm("sei"); while(1){ if(BitIsSet(system, 0)){ if(BitIsSet(system, 1)){ //Приём данных if(BitIsSet(system, 6)){ //Если приняли 1 (Когда на порту ноль, значит идёт приём лог 1) USART_SendChar('1'); if(byte_counter == 5){ //Если принимаем 5-й байт - это уже не данные, а биты чётности по столбам if(bit_counter == 4){ //Принимаем последний стоповый бит //4 Another_Format(); //Стоповый 64 бит не ноль ошибка }else{ SetBit(RFID_buffer[byte_counter], 4); //Набиваем регистр битов чётности по столбам ShiftBitRight(RFID_buffer[byte_counter]); //Сдвигаем вправо bit_counter++; } }else{ if(crc_counter == 4){ //Если принимаем бит чётности USART_SendChar('S'); if(BitIsClear(system, 4)){ //Если бит чётности - 0 Another_Format(); //Ошибка, бит должен быть 1 } crc_counter = 0; ClearBit(system, 4); //Обнуляем бит чётности в регистре, что бы проверить следующие 4 бита if(bit_counter == 8){ //Если приняли 8 бит, значит это 1 байт bit_counter = 0; byte_counter++; // Увеличиваем счётчик принятых байтов } }else{ SetBit(RFID_buffer[byte_counter], 7); //Набиваем регистр if(bit_counter < 7){ShiftBitRight(RFID_buffer[byte_counter]);} //Сдвигаем вправо, если бит не последний CalculateCRC(system, 4); //Расчёт чётности. Просто делаем исключающее или 4 бита регистра system и лог единицы. Получится в цикле если будет 1,3 единицы, бит будет - 1, если 2, 4 - бит будет 0 bit_counter++; crc_counter++; } } }else{ //Если приняли 0 (Когда напорту один, значит идёт приём лог. 0) USART_SendChar('0'); if(byte_counter == 5){ if(bit_counter == 4){ //Принимаем последний стоповый бит //4 SetBit(system, 2); //Так как приняли 0, то это правильный стоп-бит и устанавливаем флаг, что бы разрешить далее проверку чётности столбов }else{ ShiftBitRight(RFID_buffer[byte_counter]); // Просто сдвигаем регистр, так как 0 в этом случае запишется автоматически bit_counter++; } }else{ if(crc_counter == 4){ //Если принимаем бит чётности USART_SendChar('S'); if(BitIsSet(system, 4)){ //Если бит чётности - 1 Another_Format(); //Ошибка, бит должен быть 0 } crc_counter = 0; ClearBit(system, 4); //Обнуляем бит чётности в регистре, что бы проверить следующие 4 бита if(bit_counter == 8){ bit_counter = 0; byte_counter++; } }else{ ClearBit(RFID_buffer[byte_counter], 7); //Набиваем ноль, так как при 7 бите сдвигать не будем. А если не сдвинуть, 0 не запишется if(bit_counter < 7){ShiftBitRight(RFID_buffer[byte_counter]);} bit_counter++; crc_counter++; } } } }else{ //Приём заголовка if(BitIsSet(system, 6)){ USART_SendChar('1'); bit_counter++; }else{ Another_Format(); } if(bit_counter == 9){ SetBit(system, 1); bit_counter = 0; } } ClearBit(system, 0); } if(BitIsSet(system, 2)){//вычисление чётности столбов for(bit_counter = 0; bit_counter < 4; bit_counter++){ //Прогон для битов for(byte_counter = 0; byte_counter < 5; byte_counter++){ //Прогон для байтов if(BitIsSet(RFID_buffer[byte_counter], bit_counter)){ CalculateCRC(system, 4); } if(BitIsSet(RFID_buffer[byte_counter], (bit_counter + 4))){ CalculateCRC(system, 4); } } if(BitIsSet(system, 4)){ if(!(RFID_buffer[5] & (1 << bit_counter))){ Another_Format(); break; }else{ SetBit(system, 5); } }else{ if(RFID_buffer[5] & (1 << bit_counter)){ Another_Format(); break; }else{ SetBit(system, 5); } } ClearBit(system, 4); } if(BitIsSet(system, 5)){ char id[1]; sprintf(id, "%hhX", RFID_buffer[0]); USART_SendChar('['); for(unsigned char ii = 0; ii < strlen(id); ii++){ USART_SendChar(id[ii]); } USART_SendChar(']'); id[1] = 0; sprintf(id, "%hhX%hhX%hhX%hhX", RFID_buffer[1], RFID_buffer[2], RFID_buffer[3], RFID_buffer[4]); for(unsigned char ii = 0; ii < strlen(id); ii++){ USART_SendChar(id[ii]); } ClearBit(system, 2); break; } } } }
|
|