Программирование PIC - получить значение нескольких кнопок для порта

Я изучаю PIC (pic18f4550) и новичок в программировании микроконтроллеров. Я пытаюсь получить значение трех кнопок на PORTA и отправить его на светодиодную матрицу 8x8 в виде координат X через 74LS595 . Проблема в том, что значение, поступающее на светодиодную матрицу, не меняется, когда я нажимаю кнопки для создания другого значения. Я моделирую на Proteus, поэтому, думаю, мне не нужна функция устранения дребезга. Вот мой код и схема:

#include<p18f4550.h>

#define SCK LATBbits.LATB0
#define DATA PORTBbits.RB1
#define SCL PORTBbits.RB2

void Data_in(unsigned char k){
    DATA=k;
    SCK=0;
    SCK=1;
}

void LatchData(){
    SCL=0;
    SCL=1;
}

void Send1byte(unsigned char data)
{
    unsigned char i,temp;
    for(i=0;i<8;i++)
    {
        temp = data & (1<<i);
        if(temp)
        {
            DATA = 1;
        }
        else
        {
            DATA = 0;
        }

        SCK = 0;
        SCK = 1;
    }

SCL = 0;
SCL = 1;
}

unsigned char getMatrixX(unsigned char in_X)
{

    switch(in_X)
    {
        case 0:      // the value stuck here
        return 0b01111111;
    case 1:
        return 0b10111111;
    case 2:
        return 0b11011111;
    case 3:
        return 0b11101111;
    case 4:
        return 0b11110111;
    case 5:
        return 0b11111011;
    case 6:
        return 0b11111101;
    case 7:
        return 0b11111110;
    default:
        return 0b11111111;
    }
}

void main()
{

    TRISA = 1;
    TRISC = 1;

    TRISB = 0;
    TRISD = 0;

    PORTD = 0x80;

    while(1){
        Send1byte(getMatrixX(LATA));
    }
}

Это ссылка на мою схему: my Schematic

Очень ценю любые решения и советы. Извините за мой плохой английский.

Во-первых, в операторе switch() вам нужен перерыв; в конце каждого дела.
спасибо за совет, но все еще не работает, кроме того, из-за инструкции по возврату я не думаю, что перерыв необходим
Вы правы, перерыв здесь не нужен.
что у тебя за кнопки? Согласно схеме, входы процессора будут подтягиваться к ~НИЗКОМУ~, когда кнопка закрыта (нажата?).
Адам, это обычная кнопка, Proteus позволяет мне удерживать ее нажатой или ненажатой во время симуляции, так что да, она низкая при нажатии и высокая, когда не нажата, я использую эти состояния для создания значения, для чтения из

Ответы (2)

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

Использование ТРИС

См. ответ от Handoko, который касается этого.

Использование регистров LAT и PORT

Вы вызываете свою функцию следующим образом: Send1byte(getMatrixX(LATA)). Я предполагаю, что вы намерены получить текущий статус кнопок ввода и отправить их этой функции.

Это не сработает, вместо этого вам нужно прочитать из регистра PORTA. Правильный код будет читаться Send1byte(getMatrixX(PORTA)).

Почему это? В даташите есть краткое пояснение:

При чтении регистра PORTA считывается состояние контактов; запись в него приведет к записи в защелку порта.

И полезная картинка:

Рис. 10-1 ПОРТ и LAT

Внутренняя линия данных, которая используется, когда вы читаете бит PORT (внизу слева, из зеленого блока), подключена к входному буферу, который поступает непосредственно с вывода ввода-вывода. Напротив, линия данных, используемая при чтении бита LAT (верхний левый, подключенный к красному блоку), считывает только состояние защелки данных. Он не подключен к входу.

Обратите внимание, что определения SCK/DATA/SCL должны работать (запись в бит PORT установит LATch), но я обычно оставляю все записи в LATch, за исключением случаев, когда это невозможно (например, двунаправленные шины).

Конфигурация аналоговых функций

Вам необходимо отключить аналоговые функции, которые мультиплексируются на контакты PORTA. См. это примечание из таблицы данных:

При сбросе при включении питания RA5 и RA3:RA0 настраиваются как аналоговые входы и считываются как «0». (раздел 10, стр. 113)

Кроме того, функция компаратора также должна быть отключена. Чтобы настроить все контакты PORTA на цифровые входы, см. регистр 21-2 (ADCON1) в таблице данных. Вы можете попробовать:

ADCON1 = 0x0F; // All digital inputs
CMCON = 0x07;  // Comparators off (note this is the POR default)

Если вы этого не сделаете, вы никогда не получите входные данные от своих коммутаторов, если только симулятор Proteus не делает необычных вещей.

Упрощение getMatrixX()

Вы можете упростить функцию getMatrixX() несколькими способами, в зависимости от того, что вам нужно: код или пространство данных. Вот тот, который использует поиск по таблице (непроверенный):

unsigned char data[8] = { 0b01111111, 0b10111111, 0b11011111, 0b11101111, 0b11110111, 0b11111011, 0b11111101, 0b01111110 };

unsigned char getMatrixX(unsigned char in_X) {
  if (in_X > 7) {
    return 0xFF;
  }

  return data[in_X];
}

Было бы просто сделать то же самое со сдвигом и некоторой логикой, избегая таблицы поиска:

unsigned char getMatrixX(unsigned char in_X) {
  if (in_X > 7) {
    return 0xFF;
  }

  return 0xFF ^ (0x80 >> in_X);
}
Супер ответ Дэвид, это сработало, это действительно сработало! Аналоговая функция - это проблема, ваше объяснение LAT и таблица поиска также очень помогают мне, я не понимал этого до сих пор. Вы просто спасете мой день, я проголосую за вас, когда у меня будет достаточно репутации.
Рад, что это помогло. Всегда проверяйте раздел таблицы данных под названием «СВОДКА РЕГИСТРОВ, СВЯЗАННЫХ С PORTA», например Таблицу 10-2 для PIC 18F4550. Это может быть очень полезно для отслеживания других функций, которые необходимо отключить.

Прежде всего, вам нужно правильно настроить ввод и вывод.

Вы использовали TRISA = 1;, что означает, что только RA0 является ВХОДОМ. Пожалуйста, измените это на TRISA = 0b00000111;или TRISA = 0x07;, чтобы настроить все 3 кнопки как INPUT.

То же самое относится и к TRISB. Измените это значение на 0x00000111 или 0x07.

Как уже упоминал Питер, измените все свои дела на коммутаторе на:

case1:
 // TODO
 return;
case2:
 // TODO
 return;

Кроме того, я даже не вижу, где вы написали, что MCU должен делать при нажатии кнопки?

+1 за проблему с битовым шаблоном. Тем не менее, пожалуйста, отредактируйте свой ответ - перерыв; является избыточным при возврате; присутствует в случае: заявление.
спасибо за ответ, я уже пробовал TRISA = 0xFF и 0x07, это не работает, кроме того, как я комментирую, у меня уже был return, он вернул мне значение и вышел из функции, поэтому я не думаю, что мне нужны перерывы . Что касается кнопок, я хотел получить от них только значение, поэтому я поместил LATA в функцию getMatrixX, как вы можете видеть (proteus позволяет мне держать кнопку нажатой или не нажатой)
На улучшенных PIC вы должны читать из порта, писать в LATch.
@ Дэвид Это именно то, что я собирался сделать. Я не знаком с PIC, но LATCH должен быть выведен правильно? Вы хоть читать оттуда умеете?
Вы можете читать из регистра LATx, но вы просто получите значение, которое было установлено для выходной защелки. Если контакт настроен на ввод в регистре TRISx, то значение в PORTx является правильным значением для чтения для входов.
спасибо за ваше предложение, Дэвид, я только что попробовал, и до сих пор никаких признаков работы :(, я наблюдал осциллограф, imageshack.com/a/img837/7949/ci8a.png , сигнал Q0 74HC595 (4-я строка), кажется, никогда изменить, когда я меняю состояния кнопок