Я пытаюсь написать код для двоичного счетчика вверх/вниз. Задача состоит в том, чтобы зажечь 8 светодиодов (счетчик вверх), а затем изменить порядок свечения (счетчик вниз). Я пытаюсь создать массив светодиодов в своем коде, но я не знаю, как это сделать. Всякий раз, когда я использую PORTB [i], я получаю и требуется указатель ошибки, и если я использую PORTB.i, я также получаю сообщение об ошибке, как я получаю доступ к светодиодам, подключенным к portb? Это мой первый опыт работы с микроконтроллерами в целом, и я был бы очень признателен за вашу помощь. Вот мой код:
char LED_Direction at TRISB;
void main() {
int i;
LED_Direction=0x00;
PORTB=0x00;
//sbit LED_Array [8] = {PORTB.0,PORTB.1,PORTB.2,PORTB.3,PORTB.4,PORTB.5,PORTB.6,PORTB.7};
while(1)
{
for (i=0; i<8; i++)
{
//LED_Array [i] = 1;
PORTB[i]=1;
Delay_ms(1000);
//LED_Array [i] = 0;
PORTB.i=1;
}
for (i=7; i>-1; i--)
{
//LED_Array [i] = 1;
PORTB.i=1;
Delay_ms(1000);
PORTB.i=0;
//LED_Array [i] = 0;
}
}
}
PORTB не является ни структурой, ни массивом (или указателем).
Каждый бит в значении, которое вы ему присваиваете, напрямую соответствует выводу.
Ваша строка кода в начале main(), которая гласит: «PORTB=0x00;» это правильный способ присваивать значения PORTB.
Если вы хотите, чтобы младший бит был высоким, а остальные — низкими, установите его в 0x01 (0b00000001).
Если вы хотите, чтобы самый старший бит был старшим, а остальные — низкими, вам нужно значение 0x80 (0b10000000).
0x55 (0b01010101) или 0xAA (0b10101010) будут устанавливать чередование высоких и низких битов.
Вы также можете использовать битовый сдвиг для установки определенного бита, поэтому (1 << 3) установит 3-й бит и так далее.
PORTB действует как целое число (int). Когда вы пишете в PORTB, вы записываете все 8 бит одновременно. Вы можете использовать только квадратные скобки (var[i]) с массивами и поля (var.fieldname) со структурами. Вы не можете использовать переменную в имени поля.
Чтобы установить и очистить биты, используйте побитовые операторы C:
PORTB |= (1 << 4); //Set bit 4
PORTB &= ~(1 << 6); //Clear bit 6
PORTB = 0x03; //Set bits 0 and 1, clear all others
Они позволяют использовать переменную:
PORTB |= (1 << i); //Set bit i
PORTB &= ~(1 << i); //Clear bit i
Есть и другие способы сделать то, что вы хотите, но это самый простой.
Ваш код, кажется, включает один светодиод за раз, переходя от B0 к B7 и обратно. Если вы хотите создать реальный двоичный счетчик, вы можете сделать что-то вроде этого:
unsigned long i;
while (1)
{
for (i = 0; i < 256; i++)
{
PORTB = i;
Delay_ms(1000);
}
}
На более поздних PIC лучше использовать LATB вместо PORTB.
ОБНОВЛЕНИЕ. Основное правило для побитовых операторов заключается в том, что вы выполняете ИЛИ с 1 для установки битов, И с 0 для очистки битов и XOR с 1 для переключения битов. Побитовые операции, которые я использовал выше, работают следующим образом:
PORTB |= (1 << 4); //Set bit 4
эквивалентно:
PORTB = PORTB | (1 << 4); //Set bit 4
(1 << 4) равно 00010000. В десятичном виде это , или 16. В шестнадцатеричном формате это 0x10. Оператор ИЛИ (|) выполняет операцию ИЛИ каждого бита в PORTB с соответствующим битом в (1 << 4). Например, если в PORTB установлен только первый бит, вы получите:
00000010 PORTB
| 00010000 (1 << 4)
-----------
00010010 PORTB with bit 4 set
Бит 4 устанавливается без нарушения других битов.
Очистка бита лишь немного сложнее. Начнем с бинарного примера. Если в PORTB установлены биты 2 и 4, и вы хотите очистить бит 2, вам нужно сделать следующее:
00010100 PORTB
& 11111011 Mask value for clearing bit 2
-----------
00010000 PORTB with bit 2 cleared
Бит 2 очищается, не нарушая другие биты. Видите, второй операнд почти полностью состоит из единиц? Мы могли бы записать это вручную в шестнадцатеричном виде как 0xFB:
PORTB = PORTB & 0xFB; //Clear bit 2
Но тогда тот, кто читает код, должен остановиться и подумать о том, какие биты 0xFB очищаются. Мы можем сделать код более понятным, установив для интересующего нас бита значение 2 и инвертировав результат:
~(1 << 2);
который дает:
~ 00000100 (1 << 2)
-----------
11111011 ~(1 << 2) = Mask value for clearing bit 2
Это более понятно, чем шестнадцатеричное значение:
PORTB = PORTB & ~(1 << 2); //Clear bit 2
который сокращается до:
PORTB &= ~(1 << 2) //Clear bit 2
Когда вы устанавливаете или очищаете несколько битов, чаще используют шестнадцатеричные значения вместо записи набора значений со сдвигом. Единственный способ справиться с этим — узнать, как шестнадцатеричный код соотносится с двоичным, что не очень сложно.
Одно важное предостережение заключается в том, что компиляторы C интерпретируют числа как целые числа со знаком. Если int имеет длину всего 16 бит (что часто верно для микроконтроллеров), то что-то вроде этого может дать сбой:
unsigned long a;
a = (1 << 20); //Needs more than 16 bits -- too big for an int!
//a could now be equal to zero
Вы можете исправить это, приведя одно из чисел к типу long. Сделайте его беззнаковым, чтобы избежать предупреждений, когда установлен верхний бит:
unsigned long a;
a = (1UL << 20); //Should now work correctly
Почти всегда лучше использовать uint8_t, uint16_t и uint32_t from вместо собственных типов C, но использование суффикса UL все еще распространено.
PORTB |= (1 << 4); //Set bit 4
сдвигает ли оно число 1 на четыре бита влево или результат с предыдущим значением для PORTB? я тоже в замешательствеPORTB &= ~(1 << 6)
You can only use square brackets (var[i]) with arrays, and fields (var.fieldname) with structures.
я называл sbit RED_LED at PORTC.B5;
конкретный светодиод, и мне было интересно, чем он отличается? @АдамХаунchar LED_Direction at TRISB;
void main()
{
int i;
LED_Direction=0x00;
PORTB=0x00;
//sbit LED_Array [8] = {PORTB.0,PORTB.1,PORTB.2,PORTB.3,PORTB.4,PORTB.5,PORTB.6,PORTB.7};
while(1)
{
for (i=0; i<8; i++)
{
PORTB = 1 << i;
Delay_ms(1000);
}
for (i=7; i>-1; i--)
{
PORTB = 1 << i;
Delay_ms(1000);
}
PORTB = 0;
}
}
ПлазмаHH
Немо
Дэн Лакс
Немо