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

Светодиодиодна индикация на PIC18F6722

1) За return должно следовать выражение в скобках, которое может выполняться и переноситься в необходимый участок схемы. В данном случае в скобки берётся не все выражение, а только часть. Т.е. скобки ставить не обязательно и так можно делать?

За return должно следовать выражение того же типа, которое должна возвращать функция.

В данном случае объявлена функция, которая ничего не возвращает, и писать после return ничего нельзя.

Про скобки - это такая рекомендация для удобочитаемости. Необязательная, и лично я пишу без скобок.

 

2) Знак << 8 означает поразрядный сдвиг влево на 8 разрядов. Для чего это делать. Затем эти два разряда складывают. Зачем это делать?

Знак <<1 означает сдвиг влево на один разряд. Результат этого действия - значение умножается на 2. Подобная методика умножения используется в "мелких" контроллерах, которые не имеют аппаратного умножителя вовсе (или этот умножитель работает очень медленно). Аналогично можно делить (аппаратное деление - штука вообще редкая).

Выяснить, что получается при сдвиге на 8 разрядов, предлагаю самостоятельно.

Также самостоятельно предлагаю разобраться, как АЦП раскладывает результаты своей работы по регистрам ADRESL и ADRESH, и что надо сделать, чтобы собрать его в одну переменную.

 

Если вкратце, читать, читать и ещё раз читать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо! Программу сделал. Код получился следующий:

 

#include <p18f6722.h>
#include <stdio.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 LED_CODE_0 0xC0    //определяю переменную, при которой на индикаторе будет отображаться "0"
#define LED_CODE_1 0xF9    //определяю переменную, при которой на индикаторе будет отображаться "1"
#define LED_CODE_2 0xA4    //определяю переменную, при которой на индикаторе будет отображаться "2"
#define LED_CODE_3 0xB0    //определяю переменную, при которой на индикаторе будет отображаться "3"
#define LED_CODE_4 0x99    //определяю переменную, при которой на индикаторе будет отображаться "4"
#define LED_CODE_5 0x92    //определяю переменную, при которой на индикаторе будет отображаться "5"
#define LED_CODE_6 0x82    //определяю переменную, при которой на индикаторе будет отображаться "6"
#define LED_CODE_7 0xF8    //определяю переменную, при которой на индикаторе будет отображаться "7"
#define LED_CODE_8 0x80    //определяю переменную, при которой на индикаторе будет отображаться "8"
#define LED_CODE_9 0x90    //определяю переменную, при которой на индикаторе будет отображаться "9"
#define LED_CODE_E 0x86    //определяю переменную, при которой на индикаторе будет отображаться "E"
#define LEDCODE_X 0xFF    //определяю переменную, при которой на индикаторе не будет отображаться ни один сегмент

#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
} 

char i;                //переменная i - счетчик перебора индикаторов в основной программе
char out[7];
int UREFmv, ADCcode, Umv;    //переменная "UREFmv"-величина опорного напряжения
char NADC, KATT;        //переменная "NADC"-разрядность АЦП (у PIC18F6722 - 10 bit); переменная "KATT"-коээфициент делителя (ослабления аттенюатора) на входе
float volts;            //переменная "volts" - с плавающей запятой
char buf[5+1];            //организую первый буфер для результата с АЦПр: максимальная отображаемая величина требует 5 знакомест + символ конца строки 0х00 в конце    
char buf2[2+1+3+1];    //организую второй буфер: 2 на целую часть, 1 на точку, 3 - на друбную часть, 1 - на завершающий строку символ
const char IND_ADDR[]={0,ADDR_HL1,ADDR_HL1,ADDR_HL2,ADDR_HL3,ADDR_HL4};    //организую массив, каждый элемент которого - адрес индикатора, нулевой элемент массива не используется, const - размещаю в флеш-памяти МК

#pragma code        //произвожу запись дальнейших данных в память программ

int IzmerVoltage (void)    //организую подпрограмму запуска АЦП с результатом с плавающей запятой
{
    ADCON0bits.GO=1; //запускаю преобразователь АЦП, записав 1 в бит1 регистра ADCON0
    while (ADCON0bits.GO==1); //запускается цикл проверки работы АЦП. Окончание преобразование - окончание цикла
    return ADRES*4.89;
}

void main (void)    //точка входа в основную програму
{
    ADCON0=0x15;    //разрешаю работу АЦП (бит0=1), выбираю входа AN5 (биты2-5=0101)
    ADCON1=0x09;    //AN5-аналоговый вход (биты0-3=1001), AVDD и AVSS - опорные (биты4-5=00)
    ADCON2=0x8C;    //частота работы АЦП=1,5Мгц (биты0-2=100), время 2*Tad (биты3-5=001), результат АЦП justifield справа(бит7=1)
    
    TRISD=0;    //порт D - выход
    TRISE=0;        //порт E - выход
    TRISF=1;        //порт F - вход

    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)        //главный цикл    
    {
            Umv=IzmerVoltage();                        
            sprintf (buf, "%05d", Umv);            //помещение значения с АЦП Umv в милливольтах в буфер buf, старшие незначащие цифры будут "0" (пример: "1234" - "01234")
            buf2[0]=buf[0];        //в нулевой элемент буфера buf2 ввожу нулевой элемент буфера buf
            buf2[1]=buf[1];        //в первый элемент буфера buf2 ввожу первый элемент буфера buf
            buf2[2]='.';        //в второй элемент буфера buf2 ввожу точку "."
            buf2[3]=buf[2];        //в третий элемент буфера buf2 ввожу второй элемент буфера buf
            buf2[4]=buf[3];        //в четвертый элемент буфера buf2 ввожу третий элемент буфера buf
            buf2[5]=buf[4];        //в пятый элемент буфера buf2 ввожу четвертый элемент буфера buf
            buf2[6]='\0';        //в шестой элемент буфера buf2 ввожу символ конца строки 0х00
                for (i=1;i<5;i=i+1)    //организую цикл перебора шести индикаторов и заполнения их 6 элементами массива buf2 (кроме седьмого - нулевого)
                {
                    switch (buf2[i])                    //организую перебор содержимого буфера buf2 и сравнение с символами, которые нужно выводить на индикаторы
                    {
case '.':out[i]=out[i-1]+0x80; break;    //если в массиве точка - вывожу в предыдущий индикатор точку и выход из цикла сравнения элемента, переход к следующему (break)
case '0':out[i]=LED_CODE_0; break;    //если в массиве ноль - выводить на индикатор ноль и выход из цикла сравнения элемента, переход к следующему (break)
case '1':out[i]=LED_CODE_1; break;    //если в массиве один - выводить на индикатор один и выход из цикла сравнения элемента, переход к следующему (break)
case '2':out[i]=LED_CODE_2; break;    //если в массиве два - выводить на индикатор два и выход из цикла сравнения элемента, переход к следующему (break)
case '3':out[i]=LED_CODE_3; break;    //если в массиве три - выводить на индикатор три и выход из цикла сравнения элемента, переход к следующему (break)
case '4':out[i]=LED_CODE_4; break;    //если в массиве четыре - выводить на индикатор четыре и выход из цикла сравнения элемента, переход к следующему (break)
case '5':out[i]=LED_CODE_5; break;    //если в массиве пять - выводить на индикатор пять и выход из цикла сравнения элемента, переход к следующему (break)
case '6':out[i]=LED_CODE_6; break;    //если в массиве шесть - выводить на индикатор шесть и выход из цикла сравнения элемента, переход к следующему (break)
case '7':out[i]=LED_CODE_7; break;    //если в массиве семь - выводить на индикатор семь и выход из цикла сравнения элемента, переход к следующему (break)
case '8':out[i]=LED_CODE_8; break;    //если в массиве восемь - выводить на индикатор восемь и выход из цикла сравнения элемента, переход к следующему (break)
case '9':out[i]=LED_CODE_9; break;    //если в массиве девять - выводить на индикатор девять и выход из цикла сравнения элемента, переход к следующему (break)
default: out[i]=LED_CODE_E; break;    //в противном случае - высвечивать индикацию ошибки "Е" и переход к следующему элементу (break)
                    }                                    //окончание перебора содержимого буфера buf2
                    Indicator(IND_ADDR[i],out[i]);        //вывести полученное значение на необходимый индикатор
                };                //конец цикла перебора
    }
}

 

Теперь пробую написать программу, связанную с вводом цифр с клавиатуры 3х6 на семисегментный индикатор и выполнением простейших арифметических операций – сложение, вычитание, умножение и деление. Использоваться будут 4 индикатора. Также хочеться сделать ввод дробных чисел, т.е. ставить точку.

 

Сначала хотелось бы просто реализовать ввод чисел с клавиатуры и отображением их на экране (без точки). Контакты на клавиатуре – нормально открытые.

Матрица получилась следующая:

 

post-41684-1346439009_thumb.png

 

На столбцы сигналы подаются через дешифратор D4. На дешифратор подаются сигналы А0, А1, А2 с выходов PORTA – RA0, RA1, RA2 (ножки 24, 23, 22). Сигналы с строк считываются через сигналы INT0, INT1, INT2, которые подаются на входа PORTB – RB0, RB1, RB2 (ножки 48, 47, 46).

Текст программы пока вот такой:

 

#include <p18f6722.h>

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

#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 LED_CODE_0 0xC0        //определяю переменную, при которой на индикаторе будет отображаться "0"
#define LED_CODE_1 0xF9        //определяю переменную, при которой на индикаторе будет отображаться "1"
#define LED_CODE_2 0xA4        //определяю переменную, при которой на индикаторе будет отображаться "2"
#define LED_CODE_3 0xB0        //определяю переменную, при которой на индикаторе будет отображаться "3"
#define LED_CODE_4 0x99        //определяю переменную, при которой на индикаторе будет отображаться "4"
#define LED_CODE_5 0x92        //определяю переменную, при которой на индикаторе будет отображаться "5"
#define LED_CODE_6 0x82        //определяю переменную, при которой на индикаторе будет отображаться "6"
#define LED_CODE_7 0xF8        //определяю переменную, при которой на индикаторе будет отображаться "7"
#define LED_CODE_8 0x80        //определяю переменную, при которой на индикаторе будет отображаться "8"
#define LED_CODE_9 0x90        //определяю переменную, при которой на индикаторе будет отображаться "9"
#define LED_CODE_X 0xFF        //определяю переменную, при которой на индикаторе не будет отображаться ни один сегмент

#define PORT_DATA LATD        //определяю LATD, как переменную PORT_DATA
#define PORT_ADDR LATE        //определяю LATE, как переменную PORT_ADDR
#define NUMBER_COLOWN LATA    //определяю LATA, как переменную NUMBER_COLOWN
#define NUMBER_ROW LATB    //определяю LATB, как переменную NUMBER_ROW

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
} 

char out, i;
char SIMVOL;
char buf[4+1];        //первый буфер для ввода чисел: 4 знака + символ конца строки 0х00 в конце
const int IND_ADDR[]={0,ADDR_HL4,ADDR_HL3,ADDR_HL2,ADDR_HL1};    //массив, элементы-индикаторы, нулевой элемент-не используется

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

int Nomer_klavishi (void) //Определение символа нажатой клавиши
{

TRISA=0xF8;                    //порт A - выход
TRISB=0xFF;                    //порт В - вход
ADCON1=0xF;                    //отключаю АЦП, все выводы - цифровые
SIMVOL=0;                    //значение переменной при отсутствии нажатии клавиши

    NUMBER_COLOWN=0x00;                            //выдаю 0 на столбец 1
    if (PORTBbits.RB0==0) SIMVOL=1;                //проверяю 0 на строке 1
    else if (PORTBbits.RB1==0) SIMVOL=2;        //проверяю 0 на строке 2
         else if (PORTBbits.RB2==0) SIMVOL=3;    //проверяю 0 на строке 3
    NUMBER_COLOWN=0x01;                            //выдаю 0 на столбец 2
    if (PORTBbits.RB0==0) SIMVOL=4;                //проверяю 0 на строке 1
    else if (PORTBbits.RB1==0) SIMVOL=5;        //проверяю 0 на строке 2
         else if (PORTBbits.RB2==0) SIMVOL=6;    //проверяю 0 на строке 3
    NUMBER_COLOWN=0x02;                            //выдаю 0 на столбец 3
    if (PORTBbits.RB0==0) SIMVOL=7;                //проверяю 0 на строке 1
    else if (PORTBbits.RB1==0) SIMVOL=8;        //проверяю 0 на строке 2
         else if (PORTBbits.RB2==0) SIMVOL=9;    //проверяю 0 на строке 3
    NUMBER_COLOWN=0x03;                            //выдаю 0 на столбец 4
    if (PORTBbits.RB0==0) SIMVOL=10;            //проверяю 0 на строке 1
    else if (PORTBbits.RB1==0) SIMVOL=11;        //проверяю 0 на строке 2
         else if (PORTBbits.RB2==0) SIMVOL=12;    //проверяю 0 на строке 3
    NUMBER_COLOWN=0x04;                            //выдаю 0 на столбец 5
    if (PORTBbits.RB0==0) SIMVOL=13;            //проверяю 0 на строке 1
    else if (PORTBbits.RB1==0) SIMVOL=14;        //проверяю 0 на строке 2
         else if (PORTBbits.RB2==0) SIMVOL=15;    //проверяю 0 на строке 3
    NUMBER_COLOWN=0x05;                            //выдаю 0 на столбец 6
    if (PORTBbits.RB0==0) SIMVOL=16;            //проверяю 0 на строке 1
    else if (PORTBbits.RB1==0) SIMVOL=17;        //проверяю 0 на строке 2
         else if (PORTBbits.RB2==0) SIMVOL=18;    //проверяю 0 на строке 3
    return (SIMVOL);
}

void main (void)    //точка входа в основную програму
{

    TRISD=0;        //порт D - выход
    TRISE=0;        //порт E - выход

    Indicator(ADDR_HL1,LED_CODE_X);    //сбрасываю индикатор HL1
    Indicator(ADDR_HL2,LED_CODE_X);    //сбрасываю индикатор HL2
    Indicator(ADDR_HL3,LED_CODE_X);    //сбрасываю индикатор HL3
    Indicator(ADDR_HL4,LED_CODE_X);    //сбрасываю индикатор HL4
    Indicator(ADDR_HL5,LED_CODE_X);    //сбрасываю индикатор HL5
    Indicator(ADDR_HL6,LED_CODE_X);    //сбрасываю индикатор HL6
    Indicator(ADDR_HL7,LED_CODE_X);    //сбрасываю индикатор HL7
    Indicator(ADDR_HL8,LED_CODE_X);    //сбрасываю индикатор HL8

    i=1;    //номер индикатора, в который будет вводиться символ с клавиатуры
    out=LED_CODE_X;    //пустое значение

    while (1)        //главный цикл
    {
        SIMVOL=Nomer_klavishi();


            if  (SIMVOL!=0) 
                Indicator(IND_ADDR[i+1],out);    //вывожу ранее полученное значение на следующий индикатор, если раньше не вводилось, то ввожу пустоту
            if  (SIMVOL!=0)    switch (SIMVOL)                 //начинаю цикл перебора символа для вывода на экран
                {
                case 1:out=LED_CODE_7; break;        //загорается семь
                case 2:out=LED_CODE_4; break;        //загорается четыре
                case 3:out=LED_CODE_1; break;        //загорается один
                case 4:out=LED_CODE_8; break;        //загорается восемь
                case 5:out=LED_CODE_5; break;        //загорается пять
                case 6:out=LED_CODE_2; break;        //загорается два
                case 7:out=LED_CODE_9; break;        //загорается девять
                case 8:out=LED_CODE_6; break;        //загорается шесть
                case 9:out=LED_CODE_0; break;        //загорается ноль
                case 12:out=LED_CODE_3; break;        //загорается три
                default:out=LED_CODE_X; break;        //ничего не загорается
                };

                if (SIMVOL!=0) Indicator(IND_ADDR[i],out);    //вывожу полученное значение на индикатор
                if (SIMVOL!=0) i=i+1;                        //если ранее был введен символ с клавиатуры, то следующий вводиться в следующий индикатор
    delay ();        //пауза
    }
}

 

При вводе цифр с клавиатуры текст вводиться, но ввод осуществляется справа на лево, т.е. сначала цифра вводиться в HL4, HL3, HL2 и затем в HL1. Хочется реализовать ввод, как в обычном калькуляторе, т.е. число вводиться в правый сегмент, а все введенные ранее элементы синхронно сдвигаются влево. Слышал, что есть операция memcpy и ею можно реализовать сдвиг, слышал про то, что можно использовать тип переменной long int и организовать побайтный сдвиг влево. Думаю, что можно осуществить это же ввод на цикле условия «if», но будет очень большой текст этого участка программы. Какой способ лучше выбрать?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Программу для ввода текста сделал – вводит все значения, включая точку нормально.

Возможно выглядит не сильно красиво и правильно, но ввод чисел с клавиатуры включая запятую работает.

 

#include <p18f6722.h>

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

#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 LED_CODE_0 0xC0        //определяю переменную, при которой на индикаторе будет отображаться "0"
#define LED_CODE_1 0xF9        //определяю переменную, при которой на индикаторе будет отображаться "1"
#define LED_CODE_2 0xA4        //определяю переменную, при которой на индикаторе будет отображаться "2"
#define LED_CODE_3 0xB0        //определяю переменную, при которой на индикаторе будет отображаться "3"
#define LED_CODE_4 0x99        //определяю переменную, при которой на индикаторе будет отображаться "4"
#define LED_CODE_5 0x92        //определяю переменную, при которой на индикаторе будет отображаться "5"
#define LED_CODE_6 0x82        //определяю переменную, при которой на индикаторе будет отображаться "6"
#define LED_CODE_7 0xF8        //определяю переменную, при которой на индикаторе будет отображаться "7"
#define LED_CODE_8 0x80        //определяю переменную, при которой на индикаторе будет отображаться "8"
#define LED_CODE_9 0x90        //определяю переменную, при которой на индикаторе будет отображаться "9"
#define LED_CODE_X 0xFF        //определяю переменную, при которой на индикаторе не будет отображаться ни один сегмент

#define PORT_DATA LATD        //определяю LATD, как переменную PORT_DATA
#define PORT_ADDR LATE        //определяю LATE, как переменную PORT_ADDR
#define NUMBER_COLOWN LATA    //определяю LATA, как переменную NUMBER_COLOWN
#define NUMBER_ROW LATB    //определяю LATB, как переменную NUMBER_ROW

void Deistvie_HighInt (void);            //в программе применяется высокоприоритетное прерывание

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
} 
char i,n;
char buf[6];
char out[6]; 
char SIMVOL;
char Deistvie;
char buf2[6];

#pragma interrupt Deistvie_HighInt    //Deistvie_HighInt - это прерывание
#pragma code high_vector=0x08        //high_vector - это вектор по адресу 0x08

void high_vector (void)
{
_asm GOTO Deistvie_HighInt _endasm    //переход на функцию обработки высокоприоритетного прерывания
}

void vvod_pervogo_4isla (void) //Определение символа нажатой клавиши
{
                unsigned int i;
                for (i=1;i<5;i=i+1)    //организую цикл перебора шести элементов buf для преобразования их в десятичный код
                        {
                            switch (buf[i])                        //организую перебор содержимого буфера buf и замена на десятичные знчения
                                    {
                                    case 0x7F:buf[i]='.'; break;    //замена на точку
                                    case 0xC0:buf[i]=0; break;    //замена на ноль
                                    case 0xF9:buf[i]=1; break;    //замена на один
                                    case 0xA4:buf[i]=2; break;    //замена на два
                                    case 0xB0:buf[i]=3; break;    //замена на три
                                    case 0x99:buf[i]=4; break;    //замена на четыре
                                    case 0x92:buf[i]=5; break;    //замена на пять
                                    case 0x82:buf[i]=6; break;    //замена на шесть
                                    case 0xF8:buf[i]=7; break;    //замена на семь
                                    case 0x80:buf[i]=8; break;    //замена на восемь
                                    case 0x90:buf[i]=9; break;    //замена на девять
                                    case 0xFF:buf[i]=0; break;    //пустоту также заменяю на ноль
                                    }
                        };
                sprintf (buf2, "%05d", buf);            //вношу полученные значения из буфера buf в буфер buf2, старшие незначащие цифры будут "0" (пример: "1234" - "01234")
                
                buf[0]=LED_CODE_X;    //пустое значение
                buf[1]=LED_CODE_X;    //пустое значение
                buf[2]=LED_CODE_X;    //пустое значение
                buf[3]=LED_CODE_X;    //пустое значение
                buf[4]=LED_CODE_X;    //пустое значение
}

void Deistvie_HighInt (void)
{
TRISA=0xF8;                    //порт A - выход
TRISB=0xFF;                    //порт В - вход
ADCON1=0xF;                    //отключаю АЦП, все выводы - цифровые

    if (NUMBER_COLOWN==0x03)    //проверяю 0 на столбце 4
        {
        if (PORTBbits.RB1==0) //проверяю 0 на строке 2 (плюс)
                {
                vvod_pervogo_4isla(); //переношу число из буфера buf в buf2, преобразовав его в десятичный код, очищаю buf
                Deistvie=1;            //Действие 1 - это сложение
                }
        else if (PORTBbits.RB0==0) //проверяю 0 на строке 1 (минус)
                {
                vvod_pervogo_4isla(); //переношу число из буфера buf в buf2, преобразовав его в десятичный код, очищаю buf
                Deistvie=2;            //Действие 2 - это вычитание
                }
        }
    else if (NUMBER_COLOWN==0x05)    //проверяю 0 на столбце 6
        {
        if (PORTBbits.RB2==0) //проверяю 0 на строке 3 (равно)
                {
                if (Deistvie==1)
                                {
                            //    Тут складываю два буфера (одномерных массивов)числа + вывод на индикацию
                                }
                else if (Deistvie==2)
                                {
                            //    Тут вычитаю два числа + вывод на индикацию
                                }
                }
        }
}

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

int Nomer_klavishi (void) //Определение символа нажатой клавиши
{

TRISA=0xF8;                    //порт A - выход
TRISB=0xFF;                    //порт В - вход
ADCON1=0xF;                    //отключаю АЦП, все выводы - цифровые
SIMVOL=0;                    //значение переменной при отсутствии нажатии клавиши

    NUMBER_COLOWN=0x00;                //выдаю 0 на столбец 1
    if (PORTBbits.RB0==0) SIMVOL=1;            //проверяю 0 на строке 1 (семь)
    else if (PORTBbits.RB1==0) SIMVOL=2;        //проверяю 0 на строке 2 (четыре)
         else if (PORTBbits.RB2==0) SIMVOL=3;    //проверяю 0 на строке 3 (один)
    NUMBER_COLOWN=0x01;                //выдаю 0 на столбец 2
    if (PORTBbits.RB0==0) SIMVOL=4;            //проверяю 0 на строке 1 (восемь)
    else if (PORTBbits.RB1==0) SIMVOL=5;        //проверяю 0 на строке 2 (пять)
         else if (PORTBbits.RB2==0) SIMVOL=6;    //проверяю 0 на строке 3 (два)
    NUMBER_COLOWN=0x02;                //выдаю 0 на столбец 3
    if (PORTBbits.RB0==0) SIMVOL=7;            //проверяю 0 на строке 1 (девять)
    else if (PORTBbits.RB1==0) SIMVOL=8;        //проверяю 0 на строке 2 (шесть)
         else if (PORTBbits.RB2==0) SIMVOL=9;    //проверяю 0 на строке 3 (ноль)
    NUMBER_COLOWN=0x03;                //выдаю 0 на столбец 4
    if (PORTBbits.RB0==0) SIMVOL=10;            //проверяю 0 на строке 1 (минус)
    else if (PORTBbits.RB1==0) SIMVOL=11;        //проверяю 0 на строке 2 (плюс)
         else if (PORTBbits.RB2==0) SIMVOL=12;    //проверяю 0 на строке 3 (три)
    NUMBER_COLOWN=0x04;                //выдаю 0 на столбец 5
    if (PORTBbits.RB0==0) SIMVOL=13;            //проверяю 0 на строке 1 (разделить)
    else if (PORTBbits.RB1==0) SIMVOL=14;        //проверяю 0 на строке 2 (умножить)
         else if (PORTBbits.RB2==0) SIMVOL=15;    //проверяю 0 на строке 3 (запятая)
    NUMBER_COLOWN=0x05;                //выдаю 0 на столбец 6
    if (PORTBbits.RB0==0) SIMVOL=16;            //проверяю 0 на строке 1 (не задействован)
    else if (PORTBbits.RB1==0) SIMVOL=17;        //проверяю 0 на строке 2 (не задействован)
         else if (PORTBbits.RB2==0) SIMVOL=18;    //проверяю 0 на строке 3 (равно)
    return (SIMVOL);
}

void main (void)    //точка входа в основную програму
{
    INTCONbits.RBIE=1;                //разрешаю прерывание при изменении порта RB (RB0-RB3)
    INTCON2bits.RBIP=1;                //прерывание при изменении порта RB (RB0-RB3) имеет высокий приоритет
    RCONbits.IPEN=1;                //разрешаю приоритеты прерываний
    INTCONbits.GIEL=0;                //запрещаю низкоприоритетные прерывания
    INTCONbits.GIEH=1;                //разрешаю высокоприоритетные прерывания
    
    TRISD=0;                        //порт D - выход
    TRISE=0;                        //порт E - выход

    Indicator(ADDR_HL1,LED_CODE_X);    //сбрасываю индикатор HL1
    Indicator(ADDR_HL2,LED_CODE_X);    //сбрасываю индикатор HL2
    Indicator(ADDR_HL3,LED_CODE_X);    //сбрасываю индикатор HL3
    Indicator(ADDR_HL4,LED_CODE_X);    //сбрасываю индикатор HL4
    Indicator(ADDR_HL5,LED_CODE_X);    //сбрасываю индикатор HL5
    Indicator(ADDR_HL6,LED_CODE_X);    //сбрасываю индикатор HL6
    Indicator(ADDR_HL7,LED_CODE_X);    //сбрасываю индикатор HL7
    Indicator(ADDR_HL8,LED_CODE_X);    //сбрасываю индикатор HL8

    i=1;            //номер индикатора, в который будет вводиться символ с клавиатуры
    Deistvie=0;        //номер выполняемого математического дейстия

    out[1]=LED_CODE_X;    //пустое значение
    out[2]=LED_CODE_X;    //пустое значение
    out[3]=LED_CODE_X;    //пустое значение
    out[4]=LED_CODE_X;    //пустое значение
    out[5]=LED_CODE_X;    //пустое значение

    buf[0]=LED_CODE_X;    //пустое значение
    buf[1]=LED_CODE_X;    //пустое значение
    buf[2]=LED_CODE_X;    //пустое значение
    buf[3]=LED_CODE_X;    //пустое значение
    buf[4]=LED_CODE_X;    //пустое значение

    while (1)        //главный цикл
    {
        SIMVOL=Nomer_klavishi();

            if  (SIMVOL!=0)    switch (SIMVOL)             //начинаю цикл перебора символа для вывода на экран
                {
                case 15:out[i]=out[i-1]+0x80; break;    //загорается точка
                case 1:out[i]=LED_CODE_7; break;        //загорается семь
                case 2:out[i]=LED_CODE_4; break;        //загорается четыре
                case 3:out[i]=LED_CODE_1; break;        //загорается один
                case 4:out[i]=LED_CODE_8; break;        //загорается восемь
                case 5:out[i]=LED_CODE_5; break;        //загорается пять
                case 6:out[i]=LED_CODE_2; break;        //загорается два
                case 7:out[i]=LED_CODE_9; break;        //загорается девять
                case 8:out[i]=LED_CODE_6; break;        //загорается шесть
                case 9:out[i]=LED_CODE_0; break;        //загорается ноль
                case 12:out[i]=LED_CODE_3; break;        //загорается три
                default:SIMVOL=0; break;            //ничего не загорается
                };

                if  (SIMVOL!=0)         //вывод числа на экран с сдвигом
                    {
                    if  (out[i]==out[i-1]+0x80)    //если введена точка
                                {
                                Indicator(ADDR_HL4,out[i]);        //вывожу точку 
                                buf[i]=0x7F;            //в буфер заношу точку
                                if (i==2) out[1]=LED_CODE_X;    //в случае, если точка после первой цифры, то гашу первый сегмент
                                else if (i==3)             //в случае, если точка после второй цифры, то гашу второй + сдвигаю первый
                                        {
                                        out[2]=out[1];
                                        out[1]=LED_CODE_X;
                                        }    
                                else if (i==4)                     //в случае, если точка после третей цифры, то гашу третью + сдвигаю первый,второй
                                        {
                                        out[3]=out[2];
                                        out[2]=out[1];
                                        out[1]=LED_CODE_X;
                                        };
                                i=i+1;                        //следующее число сдвигает результат на экране
                                }
                    else if (i==1)
                                {
                                Indicator(ADDR_HL1,LED_CODE_X);    //пустое значение
                                Indicator(ADDR_HL2,LED_CODE_X);    //пустое значение
                                   Indicator(ADDR_HL3,LED_CODE_X);    //пустое значение
                                Indicator(ADDR_HL4,out[i]);        //значение 1
                                buf[0]=out[i];
                                i=i+1;                        //следующее число сдвигает результат на экране
                                }
                    else if (i==2)
                                {
                                Indicator(ADDR_HL1,LED_CODE_X);    //пустое значение
                                Indicator(ADDR_HL2,LED_CODE_X);    //пустое значение
                                   Indicator(ADDR_HL3,out[1]);     //значение 1
                                Indicator(ADDR_HL4,out[i]);        //значение 2
                                buf[1]=out[i];
                                i=i+1;                            //следующее число сдвигает результат на экране
                                }
                    else if (i==3)
                                {
                                Indicator(ADDR_HL1,LED_CODE_X);    //пустое значение
                                Indicator(ADDR_HL2,out[1]);        //значение 1
                                   Indicator(ADDR_HL3,out[2]);        //значение 2
                                Indicator(ADDR_HL4,out[i]);        //значение 3
                                buf[2]=out[i];
                                i=i+1;                            //следующее число сдвигает результат на экране
                                }
                    else if (i==4)
                                {
                                Indicator(ADDR_HL1,out[1]);        //значение 1
                                Indicator(ADDR_HL2,out[2]);        //значение 2
                                   Indicator(ADDR_HL3,out[3]);        //значение 3
                                Indicator(ADDR_HL4,out[i]);        //значение 4
                                buf[3]=out[i];
                                i=i+1;                            //следующее число сдвигает результат на экране
                                }
                    else if (i==5)
                                {
                                Indicator(ADDR_HL1,out[2]);     //пустое значение
                                Indicator(ADDR_HL2,out[3]);        //значение 1
                                   Indicator(ADDR_HL3,out[4]);        //значение 2
                                Indicator(ADDR_HL4,out[5]);        //значение 3
                                buf[4]=out[i];
                                i=i+1;                            //следующее число сдвигает результат на экране
                                };
                    }
    delay ();        //пауза
    }
}

 

Теперь пробую осуществить сложение и вычитание. Для этого в тексте программы создал буфер buf, куда вводяться временно значения первого числа, после нажатия кнопки «+» или «-» должно произойти прерывание, буфер buf должен преобразоваться в десятичную форму записи и переписать свои значения в буфер buf2. Затем буфер buf обнуляется и производиться пометка переменной «Deistvie», что после нажатия кнопки «Равно» необходимо выполнить сложение или вычитание. Затем происходит возврат к процессу ввода числа в буфер buf уже второго числа.

Прерывания организовал по сигналам на выводах R0-RB2. При этом прерывание происходить будет каждый раз, при нажатии на любую клавишу, но цикл в прерывании будет выполняться только в случае нажатие кнопок «+», «-» или «Равно».

На деле прерывание почему-то не происходит. Раньше с прерывания сталкиваться не приходилось. Из-за чего прерывание может не работать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вопрос еще по поводу функции sprintf .

Могу ли я из элементов массива (к примеру [0],[5],[8],[9],[7],[1]) создать число 58971 записью

sprintf (a, "%06d", buf);

?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот зачем, интересно, мы тут кучу советов надавали?..

И ещё раз...

 

// определяю адрес первого индикатора HL1 0x03, как переменную ADDR_HL1

Во-первых, терминология неверная.

Во-вторых, комментарии "масло масляное по той причине, что оно масляное" э-э... несколько мешают восприятию.

 

 

char i,n;

Глобальные переменные так называть НЕЛЬЗЯ. Для глобальной переменной из её названия должно быть очевидно, что там внутри находится.

Для локальной это не так критично, хотя тоже некрасиво.

 

if (PORTBbits.RB0==0) SIMVOL=4; //проверяю 0 на строке 1 (восемь)

else if (PORTBbits.RB1==0) SIMVOL=5; //проверяю 0 на строке 2 (пять)

else if (PORTBbits.RB2==0) SIMVOL=6; //проверяю 0 на строке 3 (два)

Ну вот откуда очевидно, что SIMVOL=4 - это восемь, а SIMVOL=6 - это два?! Это явное место для применения дефайнов (или, что лучше, enum'а).

 

 

for (i==0; i<10000; i++); //длительность задержки опрделяется величиной i

Как уже говорили, длительность ЭТОЙ задержки определяется погодой на Марсе. Кроме того, непонятна необходимость этой задержки в принципе.

 

Могу ли я из элементов массива (к примеру [0],[5],[8],[9],[7],[1]) создать число 58971 записью

sprintf (a, "%06d", buf);

Нет, конечно. Посмотрите на типы аргументов у sprintf. Для этой задачи подойдёт sscanf, но в данном случае проще вычислять значение прямо при вводе.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот зачем, интересно, мы тут кучу советов надавали?..

Во-первых, терминология неверная.

Во-вторых, комментарии "масло масляное по той причине, что оно масляное" э-э... несколько мешают восприятию.

Глобальные переменные так называть НЕЛЬЗЯ. Для глобальной переменной из её названия должно быть очевидно, что там внутри находится.

Для локальной это не так критично, хотя тоже некрасиво.

Ну вот откуда очевидно, что SIMVOL=4 - это восемь, а SIMVOL=6 - это два?! Это явное место для применения дефайнов (или, что лучше, enum'а).

На работе у меня Интернета нет, исправления внесу на работе, там же можно сразу проверить.

 

Как уже говорили, длительность ЭТОЙ задержки определяется погодой на Марсе. Кроме того, непонятна необходимость этой задержки в принципе.

 

При нажатии клавиши может отобразиться много цифр на индикаторе. В процессе написания программы пока помогает.

 

в данном случае проще вычислять значение прямо при вводе.

А каким образом?

 

Сегодня продолжал разбираться с прерыванием - так и не возникает. Программа чучуть изменилась. Текст теперь вот такой:

http://files.mail.ru/0LTSRM

В чем может быть проблема?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

При нажатии клавиши может отобразиться много цифр на индикаторе.

Ну так надо ждать, пока пользователь отпустит клавишу. Или, по-хорошему, вводить алгоритм подавления дребезга.

 

И в третий раз говорю, что в той строчке есть ошибка.

 

 

А каким образом?

Сейчас ввод цифр производится в основном цикле, а математика - в прерывании. Может, не стоит их разносить?

 

Программа чучуть изменилась.

Надо не чучуть. По-хорошему, это надо переделывать, ни разу не пользуясь буфером обмена.

Если в программе попадается десяток одинаковых (или почти одинаковых) кусков, это большой повод задуматься, как вынести повторяющийся код в отдельную функцию.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...