А, нуда, про драйверок. Сам бы не стал использовать возможность подключения кнопок к этому драйверу, потому и в библиотеку поддержку этой функции не добавил. В итоге нужно успешно отправить всего две команды в драйвер, если получится, значит будет круто.
Как обычно, три уровня абстракции:
- периферийные функции микроконтроллера
- программный I2C интерфейс
- команды
1. Реализация программного I2C подразумевает считывание контрольного бита. И если, например, аппаратный UART для того, чтобы считать 0 или 1, анализирует 8 или даже 16 отсчетов на один бит. То в этом простом случае обойдемся и без оверсемплинга, одно считывание в середине такта.
|
так выглядит оверсемплинг, но у меня его не будет |
Итак, контроллер будет бездействовать не больше четверти периода, а это 64 такта процессора. Вывод простой, прерывания не подойдут, интерфейс опять blocking. А вот и функции инициализации таймера и задержка ровно на четверть такта.
void tmDelayInit()
{
RCC_APB2ENR |= RCC_APB2ENR_TIM16EN;
TIM16_CR1 = (uint32_t) TIM_CR1_CKD_CK_INT;
TIM16_CR1 |= (uint32_t) TIM_CR1_CEN;
TIM16_PSC = (uint32_t) 63;
TIM16_ARR = (uint32_t) 1;
TIM16_EGR |= TIM_EGR_UG;
}
void quaterTact()
{
uint32_t timeout = 1e7;
TIM16_EGR |= TIM_EGR_UG;
TIM16_SR = 0;
while( (TIM16_SR == 0) && (--timeout > 0) );
}
Инициализация как обычно, если хотите еще один перевод datasheet, может быть и организую, а так в сети их полно, все нечитаемые. Задержка сбрасывает таймер установкой бита update и ждет пока счетчик не переполнится. На всякий случай есть таймаут. Теперь о портах ввода вывода, опять эта схема с открытым коллектором, как будто обратно в 70е вернулся, ой, так оно и есть.
2. С портами закончили, перейдем к программному I2C. Все что нам нужно - вывести вот эту последовательность.
Старт бит
GPIOA_BSRR |= (1 << TM_SDA) | (1 << TM_SCL);
halfTact();
halfTact();
// start condition
GPIOA_BRR |= 1 << TM_SDA;
halfTact();
Команда, следом за ней может следовать такая же последовательность, только с данными
int ret;
for(int i=0 ; i<8 1="" byte="" gpioa_brr="" i="" if="" quatertact="" tm_scl=""> 0) {
GPIOA_BSRR |= 1 << TM_SDA;
} else {
GPIOA_BRR |= 1 << TM_SDA;
}
quaterTact();
GPIOA_BSRR |= 1 << TM_SCL;
halfTact();
}8>
Проверочный бит, если драйвер не занулил шину во время считывания бита, функция возвращает ошибку
GPIOA_BRR |= 1 << TM_SCL;
quaterTact();
GPIOA_BSRR |= 1 << TM_SDA;
quaterTact();
GPIOA_BSRR |= 1 << TM_SCL;
quaterTact();
if((GPIOA_IDR & (1 << TM_SDA)) > 0) {
ret = -1;
} else {
ret = 0;
}
quaterTact();
Стоп бит
// stop bit
GPIOA_BRR |= 1 << TM_SDA;
GPIOA_BRR |= 1 << TM_SCL;
halfTact();
GPIOA_BSRR |= 1 << TM_SCL;
halfTact();
GPIOA_BSRR |= (1 << TM_SDA) | (1 << TM_SCL);
Данная последовательность упакована в функции int tipoI2cBlockingTx1(uint8_t data) и int tipoI2cBlockingTx(uint8_t *data, uint8_t size) для одного байта (команды, состоящей из одной только команды) и для массива данных.
3. Вот теперь про команды, пойди в них разберись так просто, datasheet предлагает вот такие таблички:
Одно слово - китайская грамота. Но тем не менее, и в них тоже можно разобраться. По итогу пользователю, по моему скромному мнению, нужны будут две команды:
- Установка яркости void setBrightness(uint8_t percent), в процентах.
- Обновление экрана (будет вызываться не пользователем, а функцией printf() из предыдущего поста). void tmUpd(uint8_t *data), где data числа, выводимые на экран.
- Хоть это и не команда экрана, но про инициализацию не стоит забывать. void tmInit()
Описанные выше функции считаю тривиальными, если надо сами посмотрите как они выглядят. Исходные коды
тут,
тут,
тут и
вот тут. Управившись с портами в stm32f0 вы с легкостью добавите кусок куда с экраном и в ваш проект, и сможете выводить сообщения полноценным
printf на семисегментник.
Чистил маслят на СТМ32, оторвал камень, приклеил его обратно суперклеем не - не работает. 3aлyпилcя драйверок TM1637 на STM32 которым я чистил маслят, полез в datashit а там целая масленая грибница маслят которые чистили драйвера на TM1637 на СТМ32.
ОтветитьУдалитьмб ты питаине подать забыл?
Удалить