Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ATtiny 2313
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
indi_88
Добрый день, возникли трудности с работой с МК. Это мой первый практический опыт в паянии и работе с МК.
Есть схема ультразвукового дальномера, пока собрал кусок: питание, кнопки управление, МК и 7сегм индикатор.

Столкнулся с проблемой, когда начал писать простенькую прошивку. Цель прошивки: просто отображать какие-то крякозяблы поочереди на 3х знакоместах (использую динамику). Пишу и шьюсь через винавр:

Код
#include <avr/io.h>
void delay_7s()
{
    unsigned int k, l;
    for(l=0; l<1; l++)
    {
        for(k=0;k<65000;k++){}
    }
}    
void main()
{
    DDRB = 0xFF;
    DDRD = 0xFF;
    for(;;)
    {
        PORTB = 0b00110011;
        PORTD = 0x40;
        delay_7s();
        PORTD = 0x0;
        //
        PORTB = 0b01010101;
        PORTD = 0x20;
        delay_7s();
        PORTD = 0x0;
        //
        PORTB = 0b11001100;
        PORTD = 0x10;
        delay_7s();
        PORTD = 0x0;
    }
}

Не могу понять почему, но информация отображается сразу на всех знакоместах. Проверял прошивку в Протеусе, там все работает. Следовательно, проблема со спаянной схемой.
Меня настараживает что моя тинька, когда на выводах лог 0, выдает 1,2-1,3 В !!!. Следовательно, напряжение после ограничивающих резюков перед транзисторами, колеблется от 0,74 В (когда на выводе PD6 (PD5 или PD4) лог 0) и до 0,82 В (когда лог 1). Думаю, что проблема в этом. То есть напряжения 0,74 и 0,82 способствуют постоянному открытию транзисторов.

Опыта мало, так что надеюсь на ваше помощь!
GDI
Все ноги питания и земли подключили? У биполярных транзисторов полезно поставить резистор с базы на землю чтоб закрывались лучше. По схеме трудно что то сказать, слишком мелкая, а ссылка на главную радикала ведет. Вообще, картинки лучше прямо сюда в форум прикладывать.
indi_88
Исправил ситуацию с принтскрином.

Проблем с землей/питанием вроде нет. Прозванивал, все баги давно уже исправил
akl
Может поможет временное подключение лапы RESET к +5V.
AHTOXA
Цитата(indi_88 @ May 6 2010, 19:10) *
информация отображается сразу на всех знакоместах.


Надо сначала отключать знакоместо, а потом уже выводить цифру для следующего знакоместа.
То есть, добавить
Код
PORTD = 0x0;

перед каждым
Код
PORTB = ....;


Ну и - volatile unsigned int k, l; maniac.gif

Пардон, первое замечание снимается - прогляделsmile.gif
Сергей Борщ
Используйте кнопку для оформления исходников. Иначе их очень трудно читать и, соответственно, уменьшается желание в них вникать.
Цитата(indi_88 @ May 6 2010, 16:10) *
Код
void delay_7s()
{
    unsigned int k, l;
    for(l=0; l<1; l++)
    {
        for(k=0;k<65000;k++){}
    }
}
Этот код работать не будет. Точнее, он будет выкинут компилятором как бесполезный при включенной оптимизации (а без оптимизации компилировать не имеет смысла). Используйте встроенную функцию _delay_ms() из <util/delay.h> или хотя бы объявите переменные цикла как volatile.
А когда компилятор выкинул задержку - вваша программа исполняется быстро-быстро smile.gif


Цитата(AHTOXA @ May 6 2010, 16:45) *
То есть, добавить
Код
PORTD = 0x0;

перед каждым
Код
PORTB = ....;
Ой. Оно же и так отключит при записи PORTB =
indi_88
Я б изменил код в теме, но пропала кнопочка едит(

Поменя код на

Код
#include <avr/io.h>
#include <util/delay.h>
int main()
{
    DDRB = 0xFF;
    DDRD = 0xFF;
    for(;;)
    {
        PORTB = 0b00110011;
        PORTD = 0x40;
        _delay_ms(1000);
        PORTD = 0x0;
        //
        PORTB = 0b01010101;
        PORTD = 0x20;
        _delay_ms(1000);
        PORTD = 0x0;
        //
        PORTB = 0b11001100;
        PORTD = 0x10;
        _delay_ms(1000);
        PORTD = 0x0;
    }
    return(0);
}


Все равно выводит на 3 знакоместа. Странно, но задержка между изменением кракозяблов на 7сегм равна дето 4 сек а не 1 сек.

Что вы можете сказать про напряжение на ноге мк при лог 0 ?

Хм, почему 4 сек а не 1 сек я разобрался. Тк в мейкфайле стояла частота 4Мгц, то чего-то функция задержки работала в 4 раза дольше. Поставил 1Мгц и задержка стала 1 сек
AHTOXA
Цитата(Сергей Борщ @ May 6 2010, 20:06) *
Ой. Оно же и так отключит при записи PORTB =

Нет, там же катоды (знакоместа) на PORTD.

Цитата(indi_88 @ May 6 2010, 20:46) *
Поменя код на
Код
...
    _delay_ms(1000);


Вы очень своеобразно трактуете понятие "динамическая индикация" smile.gif Вообще-то обычно для этого переключают разряды гораздо чаще, чем раз в секунду. Раз в сто чаще.

Уменьшите задержку примерно раз в сто, и всё станет нормально. (В том числе и напряжения.)
indi_88
Цитата
Вы очень своеобразно трактуете понятие "динамическая индикация" smile.gif Вообще-то обычно для этого переключают разряды гораздо чаще, чем раз в секунду. Раз в сто чаще.


Я правильно понимаю динамическую индикацию. Просто Вы, наверное, не правильно поняли, что я хочу.
Мне надо по очереди выводить разыне крякозяблы на индикаторе.
То есть, сначало что-то показывается в течении 1 сек на первом знакоместе, остальные погашены.
Потом что-то показывается на второй знакоместе и т.д.
AHTOXA
Цитата(indi_88 @ May 6 2010, 21:08) *
Я правильно понимаю динамическую индикацию. Просто Вы, наверное, не правильно поняли, что я хочу.

Значит вы неясно выражаете свои мысли. Когда пишут "использую динамику" - это имеет вполне определённое значение.

Что касается вопроса "почему выводятся сразу на все места" - осталось лишь одно разумное объяснение - вы перепутали цоколёвку индикатора.
Сергей Борщ
Цитата(indi_88 @ May 6 2010, 17:46) *
Что вы можете сказать про напряжение на ноге мк при лог 0 ?
Ненормально. А что на базах транзисторов? Если еще больше - то у вас транзистор не той полярности (pnp) или попутаны выводы базы и коллектра. В результате в вывод стекает ток из индикатора. Других разумных объяснений нет - направление портов вы задали.
Цитата(indi_88 @ May 6 2010, 17:46) *
Хм, почему 4 сек а не 1 сек я разобрался. Тк в мейкфайле стояла частота 4Мгц, то чего-то функция задержки работала в 4 раза дольше. Поставил 1Мгц и задержка стала 1 сек
У вас тактирование от внутреннего RC 8МГц и запрограммирован фуз CKDIV. Поэтому тактирование получается 1 МГц. А компилятор высчтитывает количество циклов задержки исходя из значения F_CPU. Так что все правильно.

Цитата(AHTOXA @ May 6 2010, 18:00) *
Нет, там же катоды (знакоместа) на PORTD.
Да. Стормозил. laughing.gif
indi_88
Цитата
Значит вы неясно выражаете свои мысли

Прошу прощение)

Цитата
Что касается вопроса "почему выводятся сразу на все места" - осталось лишь одно разумное объяснение - вы перепутали цоколёвку индикатора.

Вряд ли, я меняя значение порта Б могу зажигать/тушить все сегменты знакоместа индикатора (то есть вывести все, что я захочу).

Цитата
Ненормально. А что на базах транзисторов? Если еще больше - то у вас транзистор не той полярности (pnp) или попутаны выводы базы и коллектра. В результате в вывод стекает ток из индикатора. Других разумных объяснений нет - направление портов вы задали.

Маркировка на транзисторе: BC547B
Выводы транзисторов выбирал так:
если смотреть срез корпуса, то слева направо: к б э
На базах напряжения 0,74 (лог 0) или 0,82 (лог 1) вольт.

Меня очень смущают эти напряжения. Если они не падают ниже 0,74 В, то возможно что транзисторы постоянно открыты? Следовательно, тогда будут гореть все знакоместа
Сергей Борщ
Цоколевка похожа на правду, транзистор npn.
Цитата(indi_88 @ May 6 2010, 20:58) *
На базах напряжения 0,74 (лог 0) или 0,82 (лог 1) вольт.
А что на ногах если отключить от них транзисторы?
indi_88
Купил новый мк и транзисторы, попытаюсь сделать новую разводку и заново все собрать
-SANYCH-
Попробуйте вообще убрать транзисторы и индикатор соединить прямо на микроконтроллер (тока в порте микроконтроллера будет достаточно чтобы засветить индикатор). Данные выводить на порт в инвертированном виде.
Да еще попробуйте вашу программу пошагово пройти в каком нить симуляторе (посмотрите будут ли меняться состояния пинов).
indi_88
Собрал кусок схемы на новом мк и транзисторах, с новой разводкой. проблема ушла сама собой, так что уже и нипонятно, где она была)))

Возник другой вопрос:
Как мне сделать генерацию пачки импульсов (например, штук 25), изменяя состояние ноги мк PD0. Мне надо добиться частоты 40 кГц, мой внутренний тактовый генератор настроен ан 4 Мгц. Код должен выглядеть следующим образом:

Код
PORTD |= 0b00000001;
// какая-то задержка
PORTD &= 0b11111110;
// задержка, которая дает частоту 40 кГц


Загвоздка в том, что я не очень понимаю одну вещь:
Если частота тактового 4 Мгц, то выполнение одной итерации мцу занимает 0,25*10^-6 c.
40 кГц дает период длительностью 25*10^-6 c.

Тогда импульсы должны появляться каждую 100ую итерацию мцу.
Если делать это с помощью цикла, то непонятно, сколько времени идет на проверку условий и т.д.
Вообщем как-то так))
-SANYCH-
Такие вещи лучше делать таймером.
Если хотите узнать сколько тактов уходит на весь цикл запустите симулятор и в нем посмотрите (в симуляторе есть счетчик времени)
indi_88
А если использовать такой код:

Код
    for(unsigned char i = 25; i > 0; i--)
    {
        PORTD |= 0b00000001;
        //WAITING();
        _delay_us(12.5);
        PORTD &= 0b11111110;
        _delay_us(12.5);
        //WAITING();
    }


читаю док на функцию:
Код
void _delay_ms      (double        __ms)


В симмуляторе аврстудио не хочет делать паузу в 12,5 мкс, вместо этого получаю 12 мкс.

ЗЫ Еще возник вопрос по функции дилей:
Пытался по очереди выводить что-то на знакоместа, код:
Код
    PORTB = 0x01;
    PORTD = 0x10;
    _delay_ms(1000);    
    PORTD = 0x00;
        
    PORTB = 0x02;
    PORTD = 0x20;
    _delay_ms(1000);
    PORTD = 0x00;
        
    PORTB = 0x03;
    PORTD = 0x40;
    _delay_ms(1000);
    PORTD = 0x00;


Смотрю док:
Код
The maximal possible delay is 262.14 ms / F_CPU in MHz.

When the user request delay which exceed the maximum possible one, _delay_ms() provides a decreased resolution functionality. In this mode _delay_ms() will work with a resolution of 1/10 ms, providing delays up to 6.5535 seconds (independent from CPU frequency). The user will not be informed about decreased resolution.

Я так понял, 1 секунду оно мне все-таки выдаст...
Идем дальше... В мейкфайле ставлю частоту 4000000, задержка составляет 4 сек, а не 1 сек.
Ставлю 1000000 и, о чудо, задержка равна 1 сек. Кто может объяснить почему? Да-да, я думал, что понял в чем суть, но ошибался.

ЗЫ Забыл добавить, оптимизация -Os
Сергей Борщ
Цитата(indi_88 @ May 13 2010, 00:29) *
А если использовать такой код:
То вы не сможете в это время выводить что-то на индикатор. А если выводить на индикатор в прерываниях (что, в общем-то, грамотоно), то прерывания будут вносить искажения в ваши задержки. Изучите таймер - он может формировать такие импульсы железно на выводах OCx
Цитата(indi_88 @ May 13 2010, 00:29) *
Идем дальше... В мейкфайле ставлю частоту 4000000, задержка составляет 4 сек, а не 1 сек.
Ставлю 1000000 и, о чудо, задержка равна 1 сек. Кто может объяснить почему?
Потому что процессор с завода поставляется с фузами, прошитыми на тактирование от внутреннего RC генератора 8МГц и включенным делителем (CVDIV) на 8. Отсюда получается 1 МГц тактовой частоты.
-SANYCH-
Цитата
В симмуляторе аврстудио не хочет делать паузу в 12,5 мкс, вместо этого получаю 12 мкс.


У Вас тактовая процессора 1МГц вот и получается ровно 12мкс
indi_88
Цитата
Потому что процессор с завода поставляется с фузами, прошитыми на тактирование от внутреннего RC генератора 8МГц и включенным делителем (CVDIV) на 8. Отсюда получается 1 МГц тактовой частоты.


Ну я понимаю, что включен пределитель, но я думал, что если я в мейкфайле для винавр пишу, что я хочу частоту 4000000, то компилятор при прошивке изменит нужные фбюзы, чтобы получить именно 4000000. Строго не судите, тк я вот только начал этим всем заниматься.
Сергей Борщ
Цитата(indi_88 @ May 13 2010, 12:23) *
но я думал, что если я в мейкфайле для винавр пишу, что я хочу частоту 4000000, то компилятор при прошивке изменит нужные фбюзы, чтобы получить именно 4000000.
Вы хотите от него слишком многого. А если вы напишете 1234567, у процессора ведь нет компбинации фузов для такой частоты smile.gif. Опять же, вы можете затактировать процессор от кварца или внешнего генератора на 4МГц, а как компилятор отличит такую ситуацию от внутреннего RC?
indi_88
Хм, я начинаю понимать, то есть если я в мейкфайле пишу частоты, то они автоматически делятся на 8?
Но возникает другой вопрос:
пишу:
1) 1000000 - задержка 1сек
2) 2000000 - задержка 2сек
3) 4000000 - задержка 4сек
4) 8000000 - задержка 8сек

Если я частоту увеличиваю, то период уменьшается, и, следовательно, задержка должна наоборот уменьшаться, а она увеличивается.
Вообщем, я запутался. Мне необходимо настроит ьвнутренний тактовый на 4МГц или 10МГц, и чтобы когда я пишу _delay_ms(1000), оно ждало именно 1сек.
Сергей Борщ
Цитата(indi_88 @ May 13 2010, 12:57) *
Хм, я начинаю понимать, то есть если я в мейкфайле пишу частоты, то они автоматически делятся на 8?
Нет. Вы указываете компилятору частоту, а он рассчитывает - сколько циклов надо сделать задержку для этой частоты. Допустим, вы указали частоту 1000000 и компилятор посчитал, что надо сделать (допустим) 100 циклов для указанного вами времени задержки 7 мкс.
Теперь вы указываете ему вдвое бОльшую частоту - 2000000. Естественно, чтобы получить то же время задержки 7 мкс при удвоенной скорости процессора, процессору надо сделать вдвое больше пустых циклов. А если вы реальную частоту в железе оставили ту же, то вдвое больше пустых циклов будут исполняться в 2 раза дольше, что вы и наблюдаете.
Цитата(indi_88 @ May 13 2010, 12:57) *
Мне необходимо настроит ьвнутренний тактовый на 4МГц или 10МГц, и чтобы когда я пишу _delay_ms(1000), оно ждало именно 1сек.
Отключите CKDIV. Внимательно прочитайте, какое состояние фузов CKSEL включает внутренний RC-генератор на 4 МГц и есть ли вообще возможность включить его на 4 МГц. Если нету - включайте его на 8 МГц. Главное - в makefile надо указать именно ту частоту, которой тактируется ядро. Тогда и только тогда _delay_ms(1000) даст вам задержку ровно 1 сек (при отсутствии прерываний).
indi_88
Через понипрог убрал галочку с CKDIV и все заработало как надо!
СПАСИБО БОЛЬШОЕ!
Сергей Борщ
Цитата(indi_88 @ May 13 2010, 13:28) *
Через понипрог
Раз уж вы начинающий - позвольте дать еще один совет. Если вы пользуетесь программатором на LPT - используйте в качестве софта для программирования AVReal. Один раз напишете .bat - файл для запуска и будете избавлены от возможности случайно зашить не ту компинацию фузов. Да и прошивка будет заключаться в одно двойном щелчке по иконке этого .bat вместо лазания по менюшкам лошади. вот пример .bat для прошивки через STK200/STK500 или "5 проводов":
Код
@echo off
SET FIRMWARE=release\FS-led-display

SET AVREAL=avreal32 +MEGA8 -as -p1 -o0.5MHz
SET FUSES=BODEN=0,BLEV=1,BLB0=3,BLB1=0,RSTDSBL=1,WDTON=1,BSIZ=0,BRST=1,CKSEL=F,CKOPT
=0
%AVREAL% -e -w -v -f%FUSES% -c %FIRMWARE%.hex -d %FIRMWARE%.eep
indi_88
Спасибо, но я шью через винавр и использую com-программатор
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.