Pyku_He_oTTyda 0 23 июня, 2006 Опубликовано 23 июня, 2006 · Жалоба Есть такой код: /***************************************************** Chip type : ATmega8535 Program type : Application Clock frequency : 7,372800 MHz Memory model : Small External SRAM size : 0 Data Stack size : 128 *****************************************************/ #include <mega8535.h> // 1 Wire Bus functions #asm .equ __w1_port=0x18;PORTB .equ __w1_bit=0 #endasm #include <1wire.h> #include <delay.h> // стандартная функция задержек #include <stdio.h> // Standard Input/Output functions #include <string.h> #define LED PORTB.1 // выход на индикатор чтения #define BEEP PORTB.2 // выход BEEP #define ALARM PORTB.3 // выход ALARM #define MAX_DEVICES 1 //определяем максимальное количество устройств на шине unsigned char rom_code[MAX_DEVICES][9]; //выделяет память (9 бит умноженное на кол-во устройств) unsigned char my_code_1[9]={0x01,0x1E,0x06,0xCA,0x0C,0x00,0x00,0x70,0x01}; unsigned char my_code_2[9]={0x01,0xFD,0xE2,0xCC,0x0C,0x00,0x00,0xCC,0x01}; //функция инициализации микроконтроллера void initialization(void) { // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=Out Func1=Out Func0=Out // State7=T State6=T State5=T State4=T State3=0 State2=0 State1=0 State0=0 PORTB=0x00; DDRB=0x0F; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x04; // USART initialization // USART Baud rate: 115200 // Communication Parameters: 8 Data, 1 Stop, No Parity // USART Receiver: Off // USART Transmitter: On // USART Mode: Asynchronous UBRRL=0x03; UCSRA=0x00; UCSRB=0x08; UCSRC=0x86; UBRRH=0x00; UBRRL=0x03; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00; // 1 Wire Bus initialization w1_init(); #asm("wdr") // Watchdog Timer initialization // Watchdog Timer Prescaler: OSC/2048k #pragma optsize- WDTCR=0x1F; WDTCR=0x0F; #asm("wdr") #ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif } void test_key(void) //проверка кода ключа { if(memcmp(rom_code,my_code_1,9)==0) printf("CodeOK\n\r"); else printf("CodeError\n\r"); } //функция звукового сигнала BEEP void beep(void) { unsigned char a=0; unsigned char b=0; for (b=0;b<2;b++) { for(a=0;a<150;a++) { BEEP=1; delay_us(377); BEEP=0; delay_us(377); }; delay_ms(100); }; } //oбработка прерывания по переполнению таймера TIMER1 interrupt [TIM1_OVF] void timer1_ovf_isr(void) { unsigned char i,j,devices; TCCR1B=0x00; //останавливаем таймер TIMER1 LED=1; //моргаем светодиодом delay_ms(10); LED=0; //ищем устройство командой 0xf0, в rom_codes ложится 9 байт (family-1,serial-6,CRC8-1,некоторые устройства возвращают 9 байт) devices=w1_search(0xf0,rom_code); printf("%-u DEVICE DETECTED\r",devices); //вывод через UART количества найденных устройств for (j=0;j<9;j++) //задаем, какую часть кода выводить { printf("0x%02X ",rom_code[i][j]); } printf("\r"); test_key(); TCCR1B=0x03; //запускаем таймер TIMER1 } void main(void) { initialization(); beep(); #asm("sei") // Разрешение прерываний TCCR1B=0x03; // запуск счетчика TIMER1 { begin: #asm("wdr") goto begin; } } Он подразумевает, что считывается DS1990 каждые ~0,5с, и выводит на СОМ следующее: 1 DEVICE DETECTED 0x01,0x1E,0x06,0xCA,0x0C,0x00,0x00,0x70,0x01 //номер ключа CodeOK Вот теперь вопрос, иногда вместо реального номера ключа пишет: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 хотя устройство на шине определяется и выводится Code OK. иногда вместо нулей выводится неправильный код, сразу после включения (мусор в ОЗУ?)) Иногда работает как часы... Вчера пару часов пытался выяснить закономерность, неполучилось. Подразумеваю, что проблема в железе, сегодня буду бится дальше. P.S. Mega шилась раз 50 - 100, может здесь засада? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 23 июня, 2006 Опубликовано 23 июня, 2006 · Жалоба RE: P.S. Mega шилась раз 50 - 100, может здесь засада? У меня на макетке МК в день перешиваются раз по 10! и на всех (пока ))) ) ферификация проходит успешно, хотя МК уже более года, так что трабл явно не здесь. Если датчики ВСЕГДА определяются успешно, значит, вероятно, причина в передаче данных от МК к РС. Попробуйте printf заменить чем то своим, проверенным и надежным, или, для начала, сбавьте скорость) а то у Вас аж 115200 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergSit 0 23 июня, 2006 Опубликовано 23 июня, 2006 (изменено) · Жалоба for (j=0;j<9;j++) //задаем, какую часть кода выводить { printf("0x%02X ",rom_code[j]); } Утебя не определено значение переменная i. Надо писать так. printf("0x%02X ",rom_code[devices][j]); Если конечно devices =1 Изменено 23 июня, 2006 пользователем SergSit Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
beer_warrior 0 23 июня, 2006 Опубликовано 23 июня, 2006 · Жалоба Для начала, отладте все по частям - устройство опознается каждый раз? ОК едем дальше. Убираем printf() и сбрасываем буфер обычной процедурой(как в даташите) в hex-терминал. Нормально? заменяем printf() на sprintf() и выбрасываем буфер одним ударом. И так далее в этом ключе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 23 июня, 2006 Опубликовано 23 июня, 2006 · Жалоба for (j=0;j<9;j++) //задаем, какую часть кода выводить { printf("0x%02X ",rom_code[j]); } Утебя не определено значение переменная i. Надо писать так. printf("0x%02X ",rom_code[devices][j]); Если конечно devices =1 Скорее всего здесь и есть ошибка - компилер не инициализирует переменную по умолчанию (а мож у меня отключенно?). Прогнал в отладчике. Этакий генератор случайных массивов получается))) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Pyku_He_oTTyda 0 23 июня, 2006 Опубликовано 23 июня, 2006 · Жалоба Спасибо! Попробую, отпишусь о результатах Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergSit 0 23 июня, 2006 Опубликовано 23 июня, 2006 · Жалоба Вроде тоже ошибку дал(((. Если мы определяем массив rome_code[devices][9], при devices на 1, то обращение к первой строке выглядит так: rome_code[0][]. Поэтому надо писать так printf("0x%02X ",rom_code[0][j]); при devices=1. Если у тебя в один момент времени на шине может находиться только один ключ DS1990 двухмерный массив определять не надо. Можно определить так rome_code[8](девятый байт не надо т.к. его в ключах DS1990 нет). По такой схеме у меня все работает. printf("0x%02X ",rom_code[j]); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Pyku_He_oTTyda 0 23 июня, 2006 Опубликовано 23 июня, 2006 · Жалоба Кажется проблема была в питании, подзарядил аккумулятор и со старым кодом пошло (старый был взят и examples). Хотя не понимаю, в чем виноват аккумулятор, на нем было 12,5 вольт на холостом ходу, а потребления никакого от макетки. Но я изменил код в соответствии с советами многоуважаемых форумчан, за что всем ОГРОМНОЕ СПАСИБО! /***************************************************** Chip type : ATmega8535 Program type : Application Clock frequency : 7,372800 MHz Memory model : Small External SRAM size : 0 Data Stack size : 128 *****************************************************/ #include <mega8535.h> // 1 Wire Bus functions #asm .equ __w1_port=0x18;PORTB .equ __w1_bit=0 #endasm unsigned char rom_code[9]; //выделяет память (9 бит умноженное на кол-во устройств) unsigned char my_code_1[9]={0x01,0x1E,0x06,0xCA,0x0C,0x00,0x00,0x70,0x01}; void test_key(void) { if(memcmp(rom_code,my_code_1,9)==0) // сравниваем код, полученный от ключа с заданным printf("CodeOK "); // вывод сообщения else printf("CodeError "); } //функция звукового сигнала BEEP void beep(void) { unsigned char a=0; unsigned char b=0; for (b=0;b<2;b++) { for(a=0;a<150;a++) { BEEP=1; delay_us(377); BEEP=0; delay_us(377); }; delay_ms(100); }; } //oбработка прерывания по переполнению таймера TIMER1 interrupt [TIM1_OVF] void timer1_ovf_isr(void) { unsigned char j,devices; TCCR1B=0x00; //останавливаем таймер TIMER1 LED=1; //моргаем светодиодом delay_ms(10); LED=0; //ищем устройство командой 0xf0, в rom_codes ложится 9 байт (family-1,serial-6,CRC8-1,некоторые устройства возвращают 9 байт) devices=w1_search(0xf0,rom_code); if (devices==1) // если устройство присуствует, выводим подтверждение и номер { printf("Device Detected "); for (j=0;j<9;j++) //задаем, какую часть кода выводить { printf("0x%02X ",rom_code[j]); } printf(" "); }; test_key(); TCCR1B=0x03; //запускаем таймер TIMER1 } void main(void) { initialization(); beep(); #asm("sei") // Разрешение прерываний TCCR1B=0x03; // запуск счетчика TIMER1 { begin: #asm("wdr") goto begin; } } (девятый байт не надо т.к. его в ключах DS1990 нет) Понятно, по даташиту нет, я согласен, но 9 у меня всегда равен 01h, не знаю почему... Пробовал для эксперимента смотреть дальше в ОЗУ = 00h. Этот момент для меня не понятен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 23 июня, 2006 Опубликовано 23 июня, 2006 · Жалоба для начала, сбавьте скорость) а то у Вас аж 115200 Зачем это? Кварц правильный, не надо ничего сбавлять. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gorby 6 25 июня, 2006 Опубликовано 25 июня, 2006 · Жалоба И я свои пять копеек. С каких пор хорошим тоном является делание громоздких операций в прерывании? Нельзя было установкой флага обойтись? А остальное делать в main. А вызов printf() из прерывания - вообще песня. А delay_ms(10) в прерывании? Считаю, что в данной задаче никакой обоснованной необходимости в прерывании не было. Нужен тик таймера - запустите таймер и анализируйте поллом в main. Тем более что ничего другого не делается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Shurmas 0 25 июня, 2006 Опубликовано 25 июня, 2006 · Жалоба для начала, сбавьте скорость) а то у Вас аж 115200 Зачем это? Кварц правильный, не надо ничего сбавлять. Кроме кварца важно еще как сделан физический интерфейс. 115200 не каждому подсилу. С каких пор хорошим тоном является делание громоздких операций в прерывании? Нельзя было установкой флага обойтись? А остальное делать в main. А вызов printf() из прерывания - вообще песня. А delay_ms(10) в прерывании? Наверно 123 читал. И похоже не внимательно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SpiritDance 0 25 июня, 2006 Опубликовано 25 июня, 2006 · Жалоба А вызов printf() из прерывания - вообще песня. А delay_ms(10) в прерывании? Да уж... Чайникам от чайника. В итоге чайник на чайнике сидит и чайником по морде бьет. :cranky: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Pyku_He_oTTyda 0 26 июня, 2006 Опубликовано 26 июня, 2006 · Жалоба Код я переписал, заработало все. Если интересно, могу выложить после обеда. задержка на 10 мс для моргания светодиодом, что бы видеть залетели в прерывание или нет. В будующем не планируется применять Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Pyku_He_oTTyda 0 26 июня, 2006 Опубликовано 26 июня, 2006 · Жалоба С каких пор хорошим тоном является делание громоздких операций в прерывании? Нельзя было установкой флага обойтись? А остальное делать в main. А вызов printf() из прерывания - вообще песня. А delay_ms(10) в прерывании? Считаю, что в данной задаче никакой обоснованной необходимости в прерывании не было. Нужен тик таймера - запустите таймер и анализируйте поллом в main. Тем более что ничего другого не делается. Насчет красивости учту:) Чем плохо printf() в прерывании, если времени гарантированно хватает (ну просто вагон)? Кроме кварца важно еще как сделан физический интерфейс. 115200 не каждому подсилу. преобразователь на FT232 с гальванической развязкой, с железом проблем нет, стабильно работает Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Shurmas 0 26 июня, 2006 Опубликовано 26 июня, 2006 · Жалоба Чем плохо printf() в прерывании, если времени гарантированно хватает (ну просто вагон)? Надеюсь defunct вам сейчас объяснит! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться