Гость химик Опубликовано 24 Февраля, 2012 в 19:31 Жалоба Поделиться Опубликовано 24 Февраля, 2012 в 19:31 (изменено) Добрый вечер. Возникла проблема при создании монитора индикации для утройства. Пока что задача вывести из масива на семисегментники цифры 0 - 8. Тоесть цифры должны отображаться постоянно. Частота смены символов 2мс. В PROTEUSE цифры отображаются, кроме 0 - на его месте тоже 1. На плате четко отображается только 7. Все остальные почему-то быстро изменяются и плохо отображается. Первая цифра совсем не светится. Наверное я не правильно вывожу байты. //=========================== Динамическая индикация ================================= void Preparation_Transmit(void){ static unsigned char counter_2=1; temp_1=abcd[counter_2]; switch(counter_2){ case 1: {temp_2=0b00000001;break;} case 2: {temp_2=0b00000010;break;} case 3: {temp_2=0b00000100;break;} case 4: {temp_2=0b00001000;break;} case 5: {temp_2=0b00010000;break;} case 6: {temp_2=0b00100000;break;} case 7: {temp_2=0b01000000;break;} case 8: {temp_2=0b10000000;break;} case 9: {temp_2=0b00000000;temp_3++;} } Transmit_Indicate(); if(counter_2 == 9)temp_3--; counter_2++; if(counter_2 == 10) counter_2=1; } //=========================== Пересылка байт в сдвиговый ============================= void Transmit_Indicate(void){ Transmit_Bayt(temp_3); PORTC.3=1; PORTC.3=0; Transmit_Bayt(temp_2); PORTC.3=1; PORTC.3=0; Transmit_Bayt(temp_1); PORTC.3=1; PORTC.3=0; PORTC.2=1; PORTC.2=0; } //=========================== Загрузка бит в регистр ================================== unsigned char Transmit_Bayt(unsigned char data){ unsigned char di=8; while(di){ PORTC.3=1; PORTC.1=data&0x80; data<<=1; PORTC.3=0; di--; } } /******************************************************************************** *************/ /******************************************************************************** *************/ interrupt [TIM0_OVF] void timer0_ovf_isr(void) { TCNT0=0xe8; // Reinitialize Timer 0 value Preparation_Transmit(); } PORTC.1 - данные PORTC.2 - защелка PORTC.3 - строб abcd[] - массив, содержащий коды цифр abcd[]={0x14,0x77,0x4c,0x45,0x27,0x85,0x84,0x57,0x04}; Исходники с файлом PROTEUS прилогаю. Dinamo_Indicate.rarПолучение информации... Изменено 24 Февраля, 2012 в 19:35 пользователем химик Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость torip3ng Опубликовано 24 Февраля, 2012 в 21:27 Жалоба Поделиться Опубликовано 24 Февраля, 2012 в 21:27 Используйте SPI (если он свободен конечно) для загрузки регистров. Например: #include <avr/io.h> #include <avr/interrupt.h> #include <avr/wdt.h> #include <avrlibtypes.h> #define F_CPU 8000000 #include <avr/delay.h> #define SEG_A 2 #define SEG_B 8 #define SEG_C 16 #define SEG_D 128 #define SEG_E 1 #define SEG_F 4 #define SEG_G 32 #define SEG_H 64 #define DIGPORT1 PORTB #define DIGPORT2 PORTD #define DIG1 2 #define DIG2 1 #define DIG3 0 #define DIG4 7 #define onewirePIN 5 u08 dig_trf1=0,dig_trf2=0,dig_trf3=0,dig_trf4=0; volatile u08 refresh_count=0; u08 temp_flg=0; volatile long temperature=0; ISR(TIMER0_OVF_vect) { static char upd_dig=1; unsigned char to_transfer=0; DIGPORT1 &= ~(1<<DIG1); DIGPORT1 &= ~(1<<DIG2); DIGPORT1 &= ~(1<<DIG3); DIGPORT2 &= ~(1<<DIG4); if (upd_dig==1) { to_transfer=dig_trf1; DIGPORT1|=1<<DIG1; upd_dig=2; } else if (upd_dig==2) { to_transfer=dig_trf2; DIGPORT1|=1<<DIG2; upd_dig=3; } else if (upd_dig==3) { to_transfer=dig_trf3; DIGPORT1|=1<<DIG3; upd_dig=4; } else if (upd_dig==4) { to_transfer=dig_trf4; DIGPORT2|=1<<DIG4; upd_dig=1; } SPDR = to_transfer; while( !(SPSR & (1<<SPIF)) ) {;} refresh_count++; wdt_reset(); } unsigned char present_ds18b20(void){ unsigned char res; DDRC|= 1<<onewirePIN; _delay_loop_2(950); DDRC&=~(1<<onewirePIN); _delay_loop_2(130); if ((PINC&(1<<onewirePIN))==0x00) res=1; else res=0; _delay_loop_2(810); return res; } void send_ds18b20(unsigned char command){ unsigned char i, data; data=command; for(i=0;i<8;i++) { if ((data&0x01)==0x01) { DDRC|= 1<<onewirePIN; _delay_loop_2(4); DDRC&=~(1<<onewirePIN); _delay_loop_2(120); } else { DDRC|= 1<<onewirePIN; _delay_loop_2(110); DDRC&=~(1<<onewirePIN); _delay_loop_2(4); } data=data>>1; } } void receive_ds18b20(void){ unsigned char i; temperature=0; temp_flg=0; for(i=0;i<12;i++) { DDRC|= 1<<onewirePIN; _delay_loop_2(4); DDRC&=~(1<<onewirePIN); _delay_loop_1(12); if ((PINC&(1<<onewirePIN))==0x00) temperature&=~(1<<i); else { temperature|=1<<i;} _delay_loop_2(100); } } int init_mk(void){ PORTB=0x00; DDRB=0x2F; PORTC=0x00; DDRC=0x00; PORTD=0x00; DDRD=0x80; TCCR0B= _BV(CS01) | _BV(CS00); TIMSK0= _BV(TOIE0); SPCR=_BV(SPE) | _BV(MSTR); wdt_enable(WDTO_60MS); sei(); } u08 NumToByte( u08 num, u08 dot ) { u08 byte = 0; switch(num) { case 0: byte = SEG_A + SEG_B + SEG_C + SEG_D + SEG_E + SEG_F; break; case 1: byte = SEG_B + SEG_C; break; case 2: byte = SEG_A + SEG_B + SEG_G + SEG_E + SEG_D; break; case 3: byte = SEG_A + SEG_B + SEG_C + SEG_D + SEG_G; break; case 4: byte = SEG_G + SEG_B + SEG_C + SEG_F; break; case 5: byte = SEG_A + SEG_F + SEG_C + SEG_D + SEG_G; break; case 6: byte = SEG_A + SEG_G + SEG_C + SEG_D + SEG_E + SEG_F; break; case 7: byte = SEG_A + SEG_B + SEG_C; break; case 8: byte = SEG_A + SEG_B + SEG_C + SEG_D + SEG_E + SEG_F + SEG_G; break; case 9: byte = SEG_A + SEG_B + SEG_C + SEG_D + SEG_F + SEG_G; break; case '-': byte = SEG_G; break; } if ( dot ) byte |= SEG_H; return byte; } void NumToDig( u32 num, u08 *digit1, u08 *digit2, u08 *digit3, u08 *digit4) { *digit1 = 0; *digit2 = 0; *digit3 = 0; *digit4 = 0; if ( num > 9999 ) return; while ( num > 999 ) { num -= 1000; (*digit1)++; } while ( num > 99 ) { num -= 100; (*digit2)++; } while ( num > 9 ) { num -= 10; (*digit3)++; } *digit4 = num; } void measure() { if (present_ds18b20()) { send_ds18b20(0xCC); send_ds18b20(0x44); while(!(PINC&(1<<onewirePIN))); present_ds18b20(); send_ds18b20(0xCC); send_ds18b20(0xBE); receive_ds18b20(); } } void display(){ if (temperature>3000) { temperature=4096-temperature; temp_flg=1;} temperature=(temperature*625)/100; if (temp_flg) { if (temperature<1000) { NumToDig(temperature,&dig_trf1,&dig_trf2,&dig_trf3,&dig_trf4); dig_trf1=NumToByte('-',0); dig_trf2=NumToByte(dig_trf2,1); dig_trf3=NumToByte(dig_trf3,0); dig_trf4=NumToByte(dig_trf4,0); } else { temperature/=10; NumToDig(temperature,&dig_trf1,&dig_trf2,&dig_trf3,&dig_trf4); dig_trf1=NumToByte('-',0); dig_trf2=NumToByte(dig_trf2,0); dig_trf3=NumToByte(dig_trf3,1); dig_trf4=NumToByte(dig_trf4,0); } } else if (temperature>=10000) { temperature/=10; NumToDig(temperature,&dig_trf1,&dig_trf2,&dig_trf3,&dig_trf4); dig_trf1=NumToByte(dig_trf1,0); dig_trf2=NumToByte(dig_trf2,0); dig_trf3=NumToByte(dig_trf3,1); dig_trf4=NumToByte(dig_trf4,0); } else if (temperature<1000) { NumToDig(temperature,&dig_trf1,&dig_trf2,&dig_trf3,&dig_trf4); dig_trf1=0; dig_trf2=NumToByte(dig_trf2,1); dig_trf3=NumToByte(dig_trf3,0); dig_trf4=NumToByte(dig_trf4,0); } else { NumToDig(temperature,&dig_trf1,&dig_trf2,&dig_trf3,&dig_trf4); dig_trf1=NumToByte(dig_trf1,0); dig_trf2=NumToByte(dig_trf2,1); dig_trf3=NumToByte(dig_trf3,0); dig_trf4=NumToByte(dig_trf4,0); } } void main(void){ init_mk(); while(1){ wdt_reset(); if ( refresh_count > 200 ) { measure(); display(); refresh_count=0; } } } Динамическая индикация, на 4 сегмента 1 сдвиговый (74hc164). После загрузки данных в ваши регистры просто добавить защелку. Может чем то поможет. Очень тяжело читать Ваш код с "магическими числами". Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость химик Опубликовано 25 Февраля, 2012 в 13:21 Жалоба Поделиться Опубликовано 25 Февраля, 2012 в 13:21 torip3ng сказал: Очень тяжело читать Ваш код с "магическими числами". Наверное потому, что я пишу в CodeVisionAVR, а вы в WinAVR. Поверьте, ваши числа для меня имеют не меньше "магии". Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость torip3ng Опубликовано 25 Февраля, 2012 в 23:11 Жалоба Поделиться Опубликовано 25 Февраля, 2012 в 23:11 химик сказал: Наверное потому, что я пишу в CodeVisionAVR, а вы в WinAVR. Поверьте, ваши числа для меня имеют не меньше "магии". я про TCNT0=0xe8; Сразу тяжело понять на какую частоту и какой режим настроен таймер. Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость kitekat Опубликовано 26 Февраля, 2012 в 10:55 Жалоба Поделиться Опубликовано 26 Февраля, 2012 в 10:55 (изменено) Позвольте вставить свои замечания. 1. В протеусе эта схема работает, однако в реальной схеме нужны резисторы в цепи каждого диода-сегмента. 2. Максимальный ток каждого вывода 74HC595 - 20мА, при условии, что общее потребление должно быть не больше 70мА. Итого каждый сегмент должен потреблять не более 2.5мА (2.5*8=20). Если нужно больше - то найдите аналог от Texas Instruments - TPIC6B595. Либо последовательно добавить еще ULN2003/2803, но это подойдет только для индикаторов с общим анодом. 3. Примерный алгоритм должет быть такой - загоняем в регистры последовательно 24 бита данных, предварительно правильно расчитанных (сначала, как я понимаю, биты общих анодов/катодор (разрядов), и в конце - сегменты). Затем дергаем вывод защелки - для передачи этих самых данных на выход регистра. И так по кругу. Изменено 26 Февраля, 2012 в 10:59 пользователем kitekat Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость химик Опубликовано 26 Февраля, 2012 в 12:36 Жалоба Поделиться Опубликовано 26 Февраля, 2012 в 12:36 (изменено) : Изменено 26 Февраля, 2012 в 18:00 пользователем химик Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения
Для публикации сообщений создайте учётную запись или авторизуйтесь
Вы должны быть пользователем, чтобы оставить комментарий
Создать учетную запись
Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!
Регистрация нового пользователяВойти
Уже есть аккаунт? Войти в систему.
Войти