реклама на сайте
подробности

 
 
> Светодиодиодна индикация на PIC18F6722, Как правильно написать программу?
Andbiz
сообщение Aug 16 2012, 16:40
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 447
Регистрация: 16-11-08
Из: Украина, Донецк
Пользователь №: 41 684



Здравствуйте, уважаемые форумчане!
Пробую освоить микроконтроллер PIC18F6722. Программа для работы – MPLAB IDE v8.86 + компилятор С18. Программатор – MPLAB ICD3. Есть плата, на которой уже установлен данный микроконтроллер и есть светодиоды, которые можно «позажигать», чтобы немного разобраться в работе данного МК.

Вот схемы платы:
Прикрепленное изображение

Прикрепленное изображение

Прикрепленное изображение


Микроконтроллер показан на третьей схеме.
Кварц стоит внешний – на 6 Мгц. Также используется внешний сторожевой ждущий таймер ADM706, который подключен к выводу 2 (RE0), которым нужно периодически давать импульсы, чтобы сбрасывать данный таймер и он не подал сигнал на перезапуск МК (я так понимаю).

На плате есть 8 семисегментных индикаторов HL1-HL8 (KingsBright SA56-11EWA).
Я решил написать программу, при которой на них будет написаны числа 12345678.
Сигналы на выбора сегмента (D0-D7) подключены от МК к индикатору через буферный регистр хранения информации ЭКФ1533ИР22. Сигналы на разрешение включения индикатора LE4 – LE11 подаются на индикатор с того же буферного регистра ЭКФ1533ИР22, на который данные сигналы подаются с МК через дешифратор ЭКФ1533ИД7 и инвертор сигналов ЭКФ1533ЛН1. С данными микросхемами я разобрался и написал для себя таблицу значений выходов МК, при которой будет зажигаться необходимая мне комбинация цифр.

Текст программы написал следующий:

Код
#include <p18f6722.h>

#pragma config OSC = XT // Применяю внешний кварцевый резонатор
#pragma config WDT = OFF // Внутренний сторожевой таймер отключаю - применяется внешний, который нужно периодически обнулять

void main (void)
{
    TRISD = 0;
    TRISE = 0;

    PORTD = 0; // Сбрасываю значения на порте D
    PORTE = 0; // Сбрасываю значения на порте E
    
    PORTD = 0xF9; // Принимаю соответствующие значения сегментов для индикатора HL1
    PORTE = 0x3; // Разрешаю индикацию индикатора HL1

    PORTD = 0xA4; // Принимаю соответствующие значения сегментов для индикатора HL2
    PORTE = 0x4; // Разрешаю индикацию индикатора HL2

    PORTD = 0xB0; // Принимаю соответствующие значения сегментов для индикатора HL3
    PORTE = 0x5; // Разрешаю индикацию индикатора HL3

    PORTD = 0x99; // Принимаю соответствующие значения сегментов для индикатора HL4
    PORTE = 0x6; // Разрешаю индикацию индикатора HL4

    PORTD = 0x92; // Принимаю соответствующие значения сегментов для индикатора HL5
    PORTE = 0x7; // Разрешаю индикацию индикатора HL5

    PORTD = 0x82; // Принимаю соответствующие значения сегментов для индикатора HL6
    PORTE = 0x8; // Разрешаю индикацию индикатора HL6

    PORTD = 0xF8; // Принимаю соответствующие значения сегментов для индикатора HL7
    PORTE = 0x9; // Разрешаю индикацию индикатора HL7

    PORTD = 0x80; // Принимаю соответствующие значения сегментов для индикатора HL8
    PORTE = 0xA; // Разрешаю индикацию индикатора HL8
    
    while (1); // Организую бесконечный цикл, для того, чтобы индикация светодиодов была постоянной
}


Программу скомпилировал, все прошло нормально, но прошивать МК еще не стал – решил спросить совета. Как я понимаю, при данной программе на мгновение должна появиться комбинация 12345678, т.к. с вывод микроконтроллера RE0 сигнал подается на ждущий таймер и индикаторы. Данный вывод у меня будет задействован в индикации и будет периодически менять свое значение, т.е. будет сбрасываться. Правильно ли я думаю? Правильно ли я написал программу? Правильно ли я указал конфигурационные биты в начале программы?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Andbiz
сообщение Aug 21 2012, 15:40
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 447
Регистрация: 16-11-08
Из: Украина, Донецк
Пользователь №: 41 684



Написал другую программу. Предприятие, на котором я работаю, связано с обслуживание электроприводов. При этом на приводах часто применяют индикацию, при которой семисегментные индикаторы зажигают свои сегменты в соответствии с вращением двигателя – т.е. по часовой, либо против часовой. Частота изменения сегментов соответствует скорости вращения двигателя.
Предложили попробовать написать такую программу, чтобы она просто изменяла свои сегменты по часовой стрелке. Попробовал – получилась вот такая:

Код
#include <p18f6722.h>

#pragma config OSC = XT        // Применяю внешний кварцевый резонатор
#pragma config WDT = OFF    // Внутренний сторожевой таймер отключаю - применяется внешний, который нужно периодически обнулять сигналом ADR0

#define ADDR_HL1 0x3    // определяю адрес первого индикатора HL1 0x03, как переменную ADDR_HL1
#define ADDR_HL2 0x4    // определяю адрес второго индикатора HL2 0x04, как переменную ADDR_HL2
#define ADDR_HL3 0x5    // определяю адрес третьего индикатора HL3 0x05, как переменную ADDR_HL3
#define ADDR_HL4 0x6    // определяю адрес четвертого индикатора HL4 0x06, как переменную ADDR_HL4
#define ADDR_HL5 0x7    // определяю адрес пятого индикатора HL5 0x07, как переменную ADDR_HL5
#define ADDR_HL6 0x8    // определяю адрес шестого индикатора HL6 0x08, как переменную ADDR_HL6
#define ADDR_HL7 0x9    // определяю адрес седьмого индикатора HL7 0x09, как переменную ADDR_HL7
#define ADDR_HL8 0xA    // определяю адрес восьмого индикатора HL8 0x0A, как переменную ADDR_HL8
#define ADDR_HL_NO_SELECT 0x00       //определяю переменную, при которой не будет не задействован ни один индикатор HL1-HL8

#define LEDCODE_X 0xFF    //определяю переменную, при которой на индикаторе не будет отображаться ни один сегмент
#define LEDCODE_a 0xFE    //определяю переменную, при которой на индикаторе будет отображаться сегмент "a"
#define LEDCODE_b 0xFD    //определяю переменную, при которой на индикаторе будет отображаться сегмент "b"
#define LEDCODE_c 0xFB    //определяю переменную, при которой на индикаторе будет отображаться сегмент "c"
#define LEDCODE_d 0xF7    //определяю переменную, при которой на индикаторе будет отображаться сегмент "d"
#define LEDCODE_e 0xEF    //определяю переменную, при которой на индикаторе будет отображаться сегмент "e"
#define LEDCODE_f 0xDF    //определяю переменную, при которой на индикаторе будет отображаться сегмент "f"
#define LEDCODE_g 0xBF    //определяю переменную, при которой на индикаторе будет отображаться сегмент "g"

#define PORT_DATA PORTD    //определяю PORTD, как переменную PORT_DATA
#define PORT_ADDR PORTE    //определяю PORTE, как переменную PORT_ADDR

void Indicator(char addrCode, char dataCode);    //определяю функцию с именем Indicator, char - символьный тип данных

void Indicator(char addrCode, char dataCode)    //ввожу параметры функции, т.е. значения, которые будут находиться под именам addrCode и dataCode.
{
    PORT_ADDR = addrCode;    //под параметром addrCode будет значение переменной PORT_ADDR
    PORT_DATA = dataCode;    //под параметром dataCode будет значение переменной PORT_DATA
}

    void delay (void)        //организую подпрограмму задержки
    {
        unsigned int i;
        for (i==0; i<6000; i++);    //длительность задержки опрделяется величиной i
    }

void main (void)    // точка входа в саму программу
{
    TRISD = 0;    // выводы порта D микроконтроллера определяю, как выходы
    TRISE = 0;    // выводы порта Е микроконтроллера определяю, как выходы
    
    Indicator(ADDR_HL1,LEDCODE_X);    //сбрасываю индикатор HL1
    Indicator(ADDR_HL2,LEDCODE_X);    //сбрасываю индикатор HL2
    Indicator(ADDR_HL3,LEDCODE_X);    //сбрасываю индикатор HL3
    Indicator(ADDR_HL4,LEDCODE_X);    //сбрасываю индикатор HL4
    Indicator(ADDR_HL5,LEDCODE_X);    //сбрасываю индикатор HL5
    Indicator(ADDR_HL6,LEDCODE_X);    //сбрасываю индикатор HL6
    Indicator(ADDR_HL7,LEDCODE_X);    //сбрасываю индикатор HL7
    Indicator(ADDR_HL8,LEDCODE_X);    //сбрасываю индикатор HL8

           while(1)  // Организую бесконечный цикл
           {
            char j, n; // объявляю локальную переменную n - число счета и j - счетчик
            n=6;
            for (j=0;j<n;j++)    //начинаю цикл перебора сегментов
                {
                    if (j==0)
                    {
                        Indicator(ADDR_HL1,LEDCODE_a);    //зажигаю сегмент "a"
                        Indicator(ADDR_HL2,LEDCODE_a);    //зажигаю сегмент "a"
                        Indicator(ADDR_HL3,LEDCODE_a);    //зажигаю сегмент "a"
                        Indicator(ADDR_HL4,LEDCODE_a);    //зажигаю сегмент "a"
                        Indicator(ADDR_HL5,LEDCODE_a);    //зажигаю сегмент "a"
                        Indicator(ADDR_HL6,LEDCODE_a);    //зажигаю сегмент "a"
                        Indicator(ADDR_HL7,LEDCODE_a);    //зажигаю сегмент "a"
                        Indicator(ADDR_HL8,LEDCODE_a);    //зажигаю сегмент "a"
                        delay ();    //пауза
                    }
                    else if (j==1)
                    {
                        Indicator(ADDR_HL1,LEDCODE_b);    //зажигаю сегмент "b"
                        Indicator(ADDR_HL2,LEDCODE_b);    //зажигаю сегмент "b"
                        Indicator(ADDR_HL3,LEDCODE_b);    //зажигаю сегмент "b"
                        Indicator(ADDR_HL4,LEDCODE_b);    //зажигаю сегмент "b"
                        Indicator(ADDR_HL5,LEDCODE_b);    //зажигаю сегмент "b"
                        Indicator(ADDR_HL6,LEDCODE_b);    //зажигаю сегмент "b"
                        Indicator(ADDR_HL7,LEDCODE_b);    //зажигаю сегмент "b"
                        Indicator(ADDR_HL8,LEDCODE_b);    //зажигаю сегмент "b"
                        delay ();    //пауза
                    }
                    else if (j==2)
                    {
                        Indicator(ADDR_HL1,LEDCODE_c);    //зажигаю сегмент "c"
                        Indicator(ADDR_HL2,LEDCODE_c);    //зажигаю сегмент "c"
                        Indicator(ADDR_HL3,LEDCODE_c);    //зажигаю сегмент "c"
                        Indicator(ADDR_HL4,LEDCODE_c);    //зажигаю сегмент "c"
                        Indicator(ADDR_HL5,LEDCODE_c);    //зажигаю сегмент "c"
                        Indicator(ADDR_HL6,LEDCODE_c);    //зажигаю сегмент "c"
                        Indicator(ADDR_HL7,LEDCODE_c);    //зажигаю сегмент "c"
                        Indicator(ADDR_HL8,LEDCODE_c);    //зажигаю сегмент "c"
                        delay ();    //пауза
                    }
                    else if (j==3)
                    {
                        Indicator(ADDR_HL1,LEDCODE_d);    //зажигаю сегмент "d"
                        Indicator(ADDR_HL2,LEDCODE_d);    //зажигаю сегмент "d"
                        Indicator(ADDR_HL3,LEDCODE_d);    //зажигаю сегмент "d"
                        Indicator(ADDR_HL4,LEDCODE_d);    //зажигаю сегмент "d"
                        Indicator(ADDR_HL5,LEDCODE_d);    //зажигаю сегмент "d"
                        Indicator(ADDR_HL6,LEDCODE_d);    //зажигаю сегмент "d"
                        Indicator(ADDR_HL7,LEDCODE_d);    //зажигаю сегмент "d"
                        Indicator(ADDR_HL8,LEDCODE_d);    //зажигаю сегмент "d"
                        delay ();    //пауза
                    }
                    else if (j==4)
                    {
                        Indicator(ADDR_HL1,LEDCODE_e);    //зажигаю сегмент "e"
                        Indicator(ADDR_HL2,LEDCODE_e);    //зажигаю сегмент "e"
                        Indicator(ADDR_HL3,LEDCODE_e);    //зажигаю сегмент "e"
                        Indicator(ADDR_HL4,LEDCODE_e);    //зажигаю сегмент "e"
                        Indicator(ADDR_HL5,LEDCODE_e);    //зажигаю сегмент "e"
                        Indicator(ADDR_HL6,LEDCODE_e);    //зажигаю сегмент "e"
                        Indicator(ADDR_HL7,LEDCODE_e);    //зажигаю сегмент "e"
                        Indicator(ADDR_HL8,LEDCODE_e);    //зажигаю сегмент "e"
                        delay ();    //пауза
                    }
                    else if (j==5)
                    {
                        Indicator(ADDR_HL1,LEDCODE_f);    //зажигаю сегмент "f"
                        Indicator(ADDR_HL2,LEDCODE_f);    //зажигаю сегмент "f"
                        Indicator(ADDR_HL3,LEDCODE_f);    //зажигаю сегмент "f"
                        Indicator(ADDR_HL4,LEDCODE_f);    //зажигаю сегмент "f"
                        Indicator(ADDR_HL5,LEDCODE_f);    //зажигаю сегмент "f"
                        Indicator(ADDR_HL6,LEDCODE_f);    //зажигаю сегмент "f"
                        Indicator(ADDR_HL7,LEDCODE_f);    //зажигаю сегмент "f"
                        Indicator(ADDR_HL8,LEDCODE_f);    //зажигаю сегмент "f"
                        delay ();    //пауза
                    }
                }
            }
}


Программа работает, сегменты изменяются.
Вопросы:
1) Правильно ли я организовал программу?
2) Есть ли методы, при которых программа была бы более компактной?

Теперь на работе предложили написать программу, при которой был бы задействован какой-то вход под АЦП. На данный вход подается напряжение до 5 В и это напряжение должно индикатироваться на индикаторе. Точность – до сотой (0,01) вольта.

PIC18F6722 – содержит 12 аналоговых входов (5 входов на PORTF – AN0-AN4 и 7 входов на PORTF – AN5-AN11). Выводы МК AN0-AN4 задействованы для подключения клавиатуры через дешифратор D4, поэтому их использовать не получиться. Выводы – AN5-AN10 (ножки 13-18) используются на плате для вывода изображения на ЖКИ. Они выводятся напрямую на разъем Х10.
В качестве аналоговых входов выбрал AN5 и AN6.

Как я понимаю, при работе ЦАП необходимо опорное напряжение, относительно которого будет производиться измерение напряжения.
VREF+ (21 ножка МК) - не задействована и не подключена. Микросхема в корпусе 64-Pin TQFP. Шаг ножек очень мелкий, припаять провод проблематично.
VREF- (22 ножка МК) задействована в качестве выхода под дешифратор D4. Вывода AVDD и AVSS (ножки 19 и 20) не подключены - подпаяться тоже проблематично.

Как я понимаю, организовать ЦАП без использования этих входов невозможно, т.е. создание на этой плате устройства с применением ЦАП (измерение напряжения).

Верно?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 21 2012, 15:55
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Andbiz @ Aug 21 2012, 18:40) *
Программа работает, сегменты изменяются.
Вопросы:
2) Есть ли методы, при которых программа была бы более компактной?



Код
const unsigned char AddrTable[8]=
{
    ADDR_HL1,
    ADDR_HL2,
    ADDR_HL3,
    ADDR_HL4,
    ADDR_HL5,
    ADDR_HL6,
    ADDR_HL7,
    ADDR_HL8
};

const unsigned char LedCode[7]=
{
    LEDCODE_a,
    LEDCODE_b,
    LEDCODE_c,
    LEDCODE_d,
    LEDCODE_e,
    LEDCODE_f,
    LEDCODE_g
};

void Indicator(char addrCode, char dataCode);

void main ()
{
// .....
    while (1) {

        for (unsigned char j = 0; j < 6; j++ ) {
            for (unsigned char i=0; i<sizeof(AddrTable); i++) {
                Indicator(AddrTable[i], LedCode[j]);
            }
            delay ();    //пауза
        }
    }
}
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Andbiz   Светодиодиодна индикация на PIC18F6722   Aug 16 2012, 16:40
- - Andbiz   Программу записал в МК. В результате получилась сл...   Aug 17 2012, 17:29
|- - Ruslan1   на ИР22 (SN74LS373) остаются (хранятся) те данные,...   Aug 17 2012, 19:53
- - ILYAUL   Цитата1. Коментарии должны быть полезны, а не прос...   Aug 17 2012, 20:14
- - Andbiz   Большое спасибо за помощь! Цитатана ИР22 (SN7...   Aug 20 2012, 15:28
|- - Ruslan1   Цитата(Andbiz @ Aug 20 2012, 18:28) Я обр...   Aug 20 2012, 17:20
- - Andbiz   Сигнал LE1 идет на микросхему D7 ЭКФ1533ИР22 (перв...   Aug 20 2012, 17:52
- - esaulenka   Маленький совет: при написании комментариев забыть...   Aug 21 2012, 16:28
|- - _Артём_   Цитата(esaulenka @ Aug 21 2012, 19:28) Ма...   Aug 21 2012, 16:36
- - _Ivana   Да, читая комментарии я только ещё больше путаюсь ...   Aug 21 2012, 16:43
- - esaulenka   и о ЦАПах, которые на самом деле очень даже АЦП Ц...   Aug 21 2012, 17:23
- - Andbiz   _Артём_ Спасибо, понял – более компактный код можн...   Aug 22 2012, 17:01
|- - Ruslan1   Про индикацию: самое простое для разборок- это 1. ...   Aug 23 2012, 08:54
- - esaulenka   Цитата1) За return должно следовать выражение в ск...   Aug 23 2012, 11:46
- - Andbiz   Спасибо! Программу сделал. Код получился следу...   Aug 31 2012, 18:51
- - Andbiz   Программу для ввода текста сделал – вводит в...   Sep 5 2012, 14:15
- - Andbiz   Вопрос еще по поводу функции sprintf . Могу ли я и...   Sep 5 2012, 19:01
- - esaulenka   Вот зачем, интересно, мы тут кучу советов надавали...   Sep 6 2012, 11:26
|- - Andbiz   Цитата(esaulenka @ Sep 6 2012, 14:26) Вот...   Sep 6 2012, 14:50
- - esaulenka   ЦитатаПри нажатии клавиши может отобразиться много...   Sep 7 2012, 09:31


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th August 2025 - 20:44
Рейтинг@Mail.ru


Страница сгенерированна за 0.01455 секунд с 7
ELECTRONIX ©2004-2016