Я изучаю 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
Очень ценю любые решения и советы. Извините за мой плохой английский.
Есть ряд вещей, которые необходимо исправить в вашем коде, прежде чем мы сможем начать помогать с функциональными проблемами. Я перечислил несколько ниже.
См. ответ от Handoko, который касается этого.
Вы вызываете свою функцию следующим образом: Send1byte(getMatrixX(LATA))
. Я предполагаю, что вы намерены получить текущий статус кнопок ввода и отправить их этой функции.
Это не сработает, вместо этого вам нужно прочитать из регистра PORTA. Правильный код будет читаться Send1byte(getMatrixX(PORTA))
.
Почему это? В даташите есть краткое пояснение:
При чтении регистра PORTA считывается состояние контактов; запись в него приведет к записи в защелку порта.
И полезная картинка:
Внутренняя линия данных, которая используется, когда вы читаете бит 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() несколькими способами, в зависимости от того, что вам нужно: код или пространство данных. Вот тот, который использует поиск по таблице (непроверенный):
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);
}
Прежде всего, вам нужно правильно настроить ввод и вывод.
Вы использовали TRISA = 1;
, что означает, что только RA0 является ВХОДОМ. Пожалуйста, измените это на TRISA = 0b00000111;
или TRISA = 0x07;
, чтобы настроить все 3 кнопки как INPUT.
То же самое относится и к TRISB. Измените это значение на 0x00000111 или 0x07.
Как уже упоминал Питер, измените все свои дела на коммутаторе на:
case1:
// TODO
return;
case2:
// TODO
return;
Кроме того, я даже не вижу, где вы написали, что MCU должен делать при нажатии кнопки?
Питер Беннет
пользователь3669754
Дзарда
Адам Хед
пользователь3669754