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

Cegrei Ulanov

Members
  • Постов

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

  • Посещение

Достижения Cegrei Ulanov

Новичок

Новичок (1/14)

  • 10 постов на форуме
  • Неделя на форуме
  • Месяц на форуме
  • Год на форуме

Последние значки

0

Репутация

  1. Я мучался с этим кодом две недели, не так как с кодом, а как с железом. Думал датчик не работает, заказал пару, а он оказался рабочим. И этому результату на самом деле рад, теперь могу продолжать реализовывать задуманное.
  2. Спасибо за столь развернутый ответ. Мне этот код понравился из-за простоты, видел и другие примеры с использованием больше кода, а этот такой простой для начинающих) Я вернусь к вашим рекомендациям позже, и попытаюсь код улучшить.
  3. Всем Спасибо код заработал. На будущее, если кому будет нужно. ATmega16 +ds18b20.rar
  4. Да вы правы, нужно учить. Но лучше всего учить язык во время практики. Лично это я для себя открыл. Код заработал. Спасибо что вы меня поправили в #define F_CPU 1600000. - мне нужно было еще один ноль написать. Но это не точно, я еще прерывания расставил, как мне подсказали выше.
  5. Я хочу чтобы микроконтроллер смог считывать информацию с датчика температуры. Но как вы уже поняли, не получается. Я уже не первую неделю вожусь с этим датчиком. Наверно будет проще поискать другой код в интернете.
  6. Я всё равно вашу идею не смогу воплотить, я плохо знаю язык C. И даже с прерываниями, при подключения датчика к ножки моментально выдаешь ошибку, о том, что датчик не найден. В протеусе все работает отлично, когда я выставляю частоту 1 МHz, а когда больше, выдает ошибку подключения датчика. А в коде #define F_CPU 1600000. Может из-за этого. Чуть позже проверю.
  7. Добрый день, спасибо за ответ. Если это не будет затруднительно, вы можете в коде указать прерывания? Или где его нужно поставить ? Наверное здесь DS18B20_init(); // инициализация DS18B20 write_18b20(0xCC); // проверка кода датчика write_18b20(0x44); // запуск температурного преобразования _delay_ms(1000); DS18B20_init(); // инициализация DS18B20 write_18b20(0xCC); // проверка кода датчика write_18b20(0xBE); // считываем содержимое ОЗУ Temp_L = read_18b20(); // читаем первые 2 байта блокнота Temp_H = read_18b20(); temp_flag = 1; ?
  8. Добрый день. Хочу к микроконтроллеру Atmega16 подключить датчик температуры DS18B20. Для этого я пошел в гугл и нашёл код, только он был написан на Atmega8. Я его немного изменил, только вот функции с обнаружением датчика не трогал. На выходе я получил скомпилированную программу которая успешно работает в протеусе, а вот в железе микроконтроллер, всё иначе. Он не может обнаружить датчик DS18B20. И поэтому срабатывает условие if(OK_Flag == 1) // если датчик не ответил { // ставим прочерки во всех разрядах display1 = 11; display2 = 11; display3 = 11; display4 = 11; } Я думал может DS18B20 не рабочий, но как выяснилось, он рабочий. На arduino проверял. Весь код моей программы: /*** Практическое применение термодатчиков DS18B20. Простой термометр ***/ //#define F_CPU 10000000 #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> void presend(){ ////DDRA = 0xFF; //0b1111111 порт работает на выход. ///PORTA = 0x00; // Порт отключен. } //#define F_CPU 8000000UL // устанавливаем рабочую частоту контроллера //------------------0-----1-----2-----3-----4-----5-----6-----7-----8------9----dp---minus-blank #define SEG_A (1<<0) // назначение сегментов индикатора #define SEG_B (1<<1) // соответствующим битам порта LED #define SEG_C (1<<2) // A #define SEG_D (1<<3) // F B #define SEG_E (1<<4) // G #define SEG_F (1<<5) // E C #define SEG_G (1<<6) // D H #define SEG_H (1<<7) // const unsigned char SEGMENTE [15] = { (SEG_A + SEG_B + SEG_C + SEG_D + SEG_E + SEG_F), // ; zero (SEG_B + SEG_C) , // ; one (SEG_A + SEG_B + SEG_D + SEG_E + SEG_G ), // ; two (SEG_A + SEG_B + SEG_C + SEG_D + SEG_G), // ; three (SEG_B + SEG_C + SEG_F + SEG_G), // ; four (SEG_A + SEG_C + SEG_D + SEG_F + SEG_G), // ; five (SEG_A + SEG_C + SEG_D + SEG_E + SEG_F + SEG_G), // ; six (SEG_A + SEG_B + SEG_C), // ; seven (SEG_A + SEG_B + SEG_C + SEG_D + SEG_E + SEG_F + SEG_G),// ; eight (SEG_A + SEG_B + SEG_C + SEG_D + SEG_F + SEG_G), // ; nine ~(SEG_A + SEG_B + SEG_C + SEG_D + SEG_E + SEG_F + SEG_G),// ; пусто (SEG_A + SEG_F + SEG_E), // ; R (SEG_A + SEG_D + SEG_E + SEG_F + SEG_G), // ; E ( SEG_B + SEG_C + SEG_D + SEG_E + SEG_F), // ; U (SEG_A + SEG_B + SEG_C + SEG_E + SEG_F + SEG_G) // ; A }; volatile unsigned char segcounter = 0; volatile int display1 = 0, display2 = 0, display3 = 0, display4 = 0; /*** Прерывание по переполнению T2, динамическая индикация ***/ ISR (TIMER2_OVF_vect) { PORTA = 0xFF; PORTB = (1 << segcounter); switch (segcounter) { case 0: PORTA = ~(SEGMENTE[display1]); break; case 1: PORTA = ~(SEGMENTE[display2]); break; case 2: PORTA = ~((SEGMENTE[display3])|0x80); // добавляем точку break; case 3: PORTA = ~(SEGMENTE[display4]); break; } if ((segcounter++) > 2) segcounter = 0; } unsigned char Temp_H = 0,Temp_L = 0,OK_Flag = 0,temp_flag; /*** Инициализация DS18B20 ***/ unsigned char DS18B20_init(void) { PORTC &= ~(1 << PC0); // устанавливаем низкий уровень DDRC |= (1 << PC0); _delay_us(490); DDRC &= ~(1 << PC0); _delay_us(68); OK_Flag = (PINC & (1 << PC0)); // ловим импульс присутствия датчика // если OK_Flag = 0 датчик подключен, OK_Flag = 1 датчик не подключен _delay_us(422); return OK_Flag; } /*** Функция чтения байта из DS18B20 ***/ unsigned char read_18b20(void) { unsigned char i; unsigned char dat = 0; for(i = 0;i < 8;i++) { DDRC |= (1 << PC0); _delay_us(2); DDRC &= ~(1 << PC0); _delay_us(4); dat = dat >> 1; if(PINC & (1 << PC0)) { dat |= 0x80; } _delay_us(62); } return dat; } /*** функция записи байта в DS18B20 ***/ void write_18b20(unsigned char dat) { unsigned char i; for(i = 0;i < 8;i++) { DDRC |= (1 << PC0); _delay_us(2); if(dat & 0x01) { DDRC &= ~(1 << PC0); } else { DDRC |= (1 << PC0); } dat = dat >> 1; _delay_us(62); DDRC &= ~(1 << PC0); _delay_us(2); } } /*** Главная функция ***/ int main(void) { DDRA = 0xFF; DDRB |= (1 << PB0)|(1 << PB1)|(1 << PB2)|(1 << PB3); PORTA = 0x00; PORTB = 0x00; TIMSK |= (1 << TOIE2); // разрешение прерывания по таймеру2 TCCR2 |= (1 << CS21); // предделитель на 8 _delay_ms(50); unsigned int tempint = 0,tempint1,tempint2,tempint3; // переменные для целого значения температуры unsigned int temppoint = 0,temppoint1; // переменные для дробного значения температуры sei(); //глобально разрешаем прерывания while(1) { if(OK_Flag == 1) // если датчик не ответил { // ставим прочерки во всех разрядах display1 = 11; display2 = 11; display3 = 11; display4 = 11; } DS18B20_init(); // инициализация DS18B20 write_18b20(0xCC); // проверка кода датчика write_18b20(0x44); // запуск температурного преобразования _delay_ms(1000); DS18B20_init(); // инициализация DS18B20 write_18b20(0xCC); // проверка кода датчика write_18b20(0xBE); // считываем содержимое ОЗУ Temp_L = read_18b20(); // читаем первые 2 байта блокнота Temp_H = read_18b20(); temp_flag = 1; // флаг знака температуры равен 1(плюс) if(Temp_H &(1 << 3)) // проверяем бит знака температуры на равенство единице { signed int tmp; temp_flag = 0; // флаг знака равен 0(минус) tmp = (Temp_H << 8) | Temp_L; tmp = -tmp; Temp_L = tmp; Temp_H = tmp >> 8; } tempint = ((Temp_H << 4) & 0x70)|(Temp_L >> 4); // вычисляем целое значение температуры tempint1 = tempint % 1000 / 100; tempint2 = tempint % 100 / 10; tempint3 = tempint % 10; temppoint = Temp_L & 0x0F; // вычисляем дробное значение температуры temppoint = temppoint * 625; // точность температуры temppoint1 = temppoint / 1000; if(temp_flag == 0) // если флаг знака температуры равен 0, в первом разряде ставим минус tempint1 = 11; if(tempint1 < 1) // если первая цифра значения температуры меньше 1, то гасим 1 разряд индикатора tempint1 = 12; if(tempint1 == 12 && tempint2 < 1) // если первая цифра погашена и вторая цифра значения температуры меньше 1, то гасим 2 разряд индикатора tempint2 = 12; if(tempint2 < 1 && temp_flag == 0) // если вторая цифра значения температуры меньше 1 и знак равен "минус", то гасим 2 разряд индикатора tempint2 = 12; // выводим значения на дисплей display1 = tempint1; display2 = tempint2; display3 = tempint3; display4 = temppoint1; } } Результат протеуса, в качестве картинки:
  9. Всем спасибо за помощь и советы. Проблема решилась, и как и многие говорили, код был рабочий, проблема была в железе, а именно ножки DDRD 14 и 15 сломались((
  10. Я разобрался с вашим кодом. На самом деле ваша запись выглядит куда нагляднее.
  11. //Код целеком. /*** Практическое применение термодатчиков DS18B20. Простой термометр ***/ #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #define F_CPU 8000000UL // устанавливаем рабочую частоту контроллера //------------------0-----1-----2-----3-----4-----5-----6-----7-----8------9----dp---minus-blank char SEGMENTE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x80, 0x40, 0x00}; volatile unsigned char segcounter = 0; volatile int display1 = 0, display2 = 0, display3 = 0, display4 = 0; /*** Прерывание по переполнению T2, динамическая индикация ***/ ISR (TIMER2_OVF_vect) { PORTD = 0xFF; PORTB = (1 << segcounter); switch (segcounter) { case 0: PORTD = ~(SEGMENTE[display1]); break; case 1: PORTD = ~(SEGMENTE[display2]); break; case 2: PORTD = ~((SEGMENTE[display3])|0x80); // добавляем точку break; case 3: PORTD = ~(SEGMENTE[display4]); break; } if ((segcounter++) > 2) segcounter = 0; } unsigned char Temp_H = 0,Temp_L = 0,OK_Flag = 0,temp_flag; /*** Инициализация DS18B20 ***/ unsigned char DS18B20_init(void) { PORTC &= ~(1 << PC0); // устанавливаем низкий уровень DDRC |= (1 << PC0); _delay_us(490); DDRC &= ~(1 << PC0); _delay_us(68); OK_Flag = (PINC & (1 << PC0)); // ловим импульс присутствия датчика // если OK_Flag = 0 датчик подключен, OK_Flag = 1 датчик не подключен _delay_us(422); return OK_Flag; } /*** Функция чтения байта из DS18B20 ***/ unsigned char read_18b20(void) { unsigned char i; unsigned char dat = 0; for(i = 0;i < 8;i++) { DDRC |= (1 << PC0); _delay_us(2); DDRC &= ~(1 << PC0); _delay_us(4); dat = dat >> 1; if(PINC & (1 << PC0)) { dat |= 0x80; } _delay_us(62); } return dat; } /*** функция записи байта в DS18B20 ***/ void write_18b20(unsigned char dat) { unsigned char i; for(i = 0;i < 8;i++) { DDRC |= (1 << PC0); _delay_us(2); if(dat & 0x01) { DDRC &= ~(1 << PC0); } else { DDRC |= (1 << PC0); } dat = dat >> 1; _delay_us(62); DDRC &= ~(1 << PC0); _delay_us(2); } } /*** Главная функция ***/ int main(void) { DDRD = 0xFF; DDRB |= (1 << PB0)|(1 << PB1)|(1 << PB2)|(1 << PB3); PORTD = 0x00; PORTB = 0x00; TIMSK |= (1 << TOIE2); // разрешение прерывания по таймеру2 TCCR2 |= (1 << CS21); // предделитель на 8 _delay_ms(50); unsigned int tempint = 0,tempint1,tempint2,tempint3; // переменные для целого значения температуры unsigned int temppoint = 0,temppoint1; // переменные для дробного значения температуры sei(); //глобально разрешаем прерывания while(1) { if(OK_Flag == 1) // если датчик не ответил { // ставим прочерки во всех разрядах display1 = 11; display2 = 11; display3 = 11; display4 = 11; } DS18B20_init(); // инициализация DS18B20 write_18b20(0xCC); // проверка кода датчика write_18b20(0x44); // запуск температурного преобразования _delay_ms(1000); DS18B20_init(); // инициализация DS18B20 write_18b20(0xCC); // проверка кода датчика write_18b20(0xBE); // считываем содержимое ОЗУ Temp_L = read_18b20(); // читаем первые 2 байта блокнота Temp_H = read_18b20(); temp_flag = 1; // флаг знака температуры равен 1(плюс) if(Temp_H &(1 << 3)) // проверяем бит знака температуры на равенство единице { signed int tmp; temp_flag = 0; // флаг знака равен 0(минус) tmp = (Temp_H << 8) | Temp_L; tmp = -tmp; Temp_L = tmp; Temp_H = tmp >> 8; } tempint = ((Temp_H << 4) & 0x70)|(Temp_L >> 4); // вычисляем целое значение температуры tempint1 = tempint % 1000 / 100; tempint2 = tempint % 100 / 10; tempint3 = tempint % 10; temppoint = Temp_L & 0x0F; // вычисляем дробное значение температуры temppoint = temppoint * 625; // точность температуры temppoint1 = temppoint / 1000; if(temp_flag == 0) // если флаг знака температуры равен 0, в первом разряде ставим минус tempint1 = 11; if(tempint1 < 1) // если первая цифра значения температуры меньше 1, то гасим 1 разряд индикатора tempint1 = 12; if(tempint1 == 12 && tempint2 < 1) // если первая цифра погашена и вторая цифра значения температуры меньше 1, то гасим 2 разряд индикатора tempint2 = 12; if(tempint2 < 1 && temp_flag == 0) // если вторая цифра значения температуры меньше 1 и знак равен "минус", то гасим 2 разряд индикатора tempint2 = 12; // выводим значения на дисплей display1 = tempint1; display2 = tempint2; display3 = tempint3; display4 = temppoint1; } }
  12. Я только начинающий, и для меня было легче воспринять мой код, ваш код, сложный. Я воспользовался вашим кодом, всё равно не решило проблему. Скорее это в коде ошибка, а где(( Я заменил Семисегментный индикатор на новый, ошибка прежняя, a и b не загорается. На ножки PD0 которая отвечает за "a" немного тусклее горит светодиод остальных, а на ножки PD1 которая отвечает за b горит светодиод ярко. Получается сигнал есть. Я сделал 000.8 статическими специально, чтобы было потом легче настроить Семисегментный индикатор Там всё отлично, на самом деле там должны были быть три нуля и восьмерка Я тестером всё сегменты проверял, всё они рабочие, вот сейчас взял другой Семисегментный индикатор, но всё равно ошибка отображения прежняя.
  13. Добрый день, пишу программу термометр на ATmega16, в качестве готового примера взял код с интернета который был написан на ATmega8. Код в протеусе заработал, но после переноса на железо, почему-то Светодиодный индикатор a и b не хотят загораться, когда в протеусе всё хорошо. На первой картинки, изображены 0008. Код программы для упрощения, который только отвечает за вывод цифр на Светодиодный индикатор. /*** Практическое применение термодатчиков DS18B20. Простой термометр ***/ //#define F_CPU 10000000 #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> //------------------0-----1-----2-----3-----4-----5-----6-----7-----8------9----dp---minus-blank char SEGMENTE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x80, 0x40, 0x00}; volatile unsigned char zamer = 0,segcounter = 0; volatile int display1 = 0, display2 = 0, display3 = 0, display4 = 0; /*** Прерывание по переполнению T2, динамическая индикация ***/ ISR (TIMER2_OVF_vect) { PORTD = 0xFF; PORTB = (1 << segcounter); switch (segcounter) { //Выводин на экран информацию case 0: PORTD = ~(SEGMENTE[display1]); break; case 1: PORTD = ~(SEGMENTE[display2]); break; case 2: PORTD = ~((SEGMENTE[display3])|0x80); // добавляем точку break; case 3: PORTD = ~(SEGMENTE[display4]); break; } if ((segcounter++) > 2) segcounter = 0; } volatile char temp_flag = 1, Temp_H, Temp_L, OK_Flag; int main(void) { DDRD = 0xFF; DDRB |= (1 << PB0)|(1 << PB1)|(1 << PB2)|(1 << PB3); PORTD = 0x00; PORTB = 0x00; TCCR1B |= (1 << WGM12)|(1 << CS12); // Таймер 1 - отсчёт 1 сек для измерения температуры OCR1A = 2250; // Для отсчёта 1 сек TIMSK |= (1 << OCIE1A); // разрешение прерывания по сравнению А таймера 1 TIMSK |= (1 << TOIE2); // разрешение прерывания по таймеру2 TCCR2 |= (1 << CS21); // предделитель на 8 // _delay_ms(50); // unsigned int tempint,tempint1,tempint2,tempint3; // переменные для целого значения температуры // unsigned int temppoint,temppoint1; // переменные для дробного значения температуры sei(); // Глобально разрешаем прерывания while(1) { display1 = 0; //tempint1; display2 = 0;//tempint2; display3 = 0;//tempint3; display4 = 8;//temppoint1; } } А на втором фото, сам результат. Светодиодный индикатор я подключал по схеме которую предоставил производитель, а также провода всё целы, я их даже менял местами и индикаторы a и b рабочие, только вод микроконтроллер не может их запустить или нет там вообще сигнала. Компилировал я, через программу Atmel Studio 7.0, а записывал на микроконтроллер через программу AVR Studio 4.
×
×
  • Создать...