а. Вместо использования функций умножения и деления для изменения
контакты / светодиоды, используйте функции << и >>. Рекомендации: Deitel и Deitel
«C, как программировать и
https://en.wikipedia.org/wiki/Operators_in_C_and_C
Сдвиг влево value << n
- это целочисленное умножение значения на 2 ^ n или значения * (2 ^ n)
Сдвиг вправо value >> n
- целочисленное деление значения на 2 ^ n или значение / (2 ^ n))
Если у вас есть var
и вы используете один из операторов сдвига, вы берете значение, равное var
, и сдвигаете двоичные цифры (биты), представляющие его значение, влево или вправо.
Базовый пример этого:
uint8_t var = 1; //0b00000001 in binary
var <<= 1; //var is now 0b00000010, that is 1*(2^1) or 2
var >>= 1; //var is now 0b00000001, that is 2/(2^1) or 1
Существует огромное предостережение относительно использования оператора сдвига, заключающегося в том, что всякий раз, когда вы сдвигаете биты, вы заполняете 0 в противоположном направлении, в котором вы сдвигаетесь, поэтому вы должны обращать внимание на целочисленный размер.
uint8_t var = 1;
var <<= 4; //var is now 0b00010000, 4 zeros filled in on the right
var = 1;
var <<= 8; //var is now 0b00000000, because 8 zeros were filled in on the right!
Теперь, что касается того, как вы используете это для манипулирования выводами на микроконтроллере, вы должны взять некоторую переменную, которая увеличивается или уменьшается, и сдвигаться влево или вправо на эту переменную и присваивать полученное значение регистру в модуле, который управляет этим контакт, который в данном случае является модулем PORTx
. В вашем коде это будет выглядеть так:
if (switch == 1) //Button not pressed pin at 5V
{
i1 = 0; //initialize to 0
}
while (switch == 1) //Button not pressed
{
PORTC = (1 << i1++); //set will set just one pin at a time, the first will be pin 0, the next pin 1, and so on
__delay_ms(500);
if (i1 == 8){
i1 = 0; //reset variable
}
}
if (switch == 0) //Button pressed pin at ground
{
i1 = 0; //initialize to 0
}
while (switch == 0) //Button pressed
{
PORTC = (0x80 >> i1++); //this will set 1 pin at a time, the first will be pin 7, the next will be pin 6, and so on
__delay_ms(500);
if (i1 == 8)
{
i1 = 0; //reset variable
}
}
б. Измените тактовую частоту в программе на 1 МГц и сделайте
Время включения / выключения каждого светодиода .1 сек. Это должно сделать вращение
заметно быстрее (Не забудьте изменить значение _XTAL_FREQ, так как это
используется для функции __delay_ms (), встроенной в XC8)
Эта часть вашего кода:
OSCCON = 0b01101000; // 4 MHz
Фактически настраивает частоту генератора, используемого микроконтроллером для его тактового сигнала. Однако вам важно знать источник этого тактового сигнала, который в соответствии с таблицей 1034 * управляется словом конфигурации 1. Это установлено в части #pragma config FOSC=INTOSC
вашего кода.
Чтобы получить 1 МГц, вам нужно изменить эту строку на:
OSCCON = 0b01011000; // 1 MHz
Это можно найти в описании регистра OSCCON в таблице.
Функция __delay_ms
использует _XTAL_FREQ для вычисления задержки, поэтому вам предлагается изменить эту строку вашего кода:
#define _XTAL_FREQ 4000000
К этому
#define _XTAL_FREQ 1000000