Микроконтроллеры STM32 - тонкости работы, отладочные платы
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
Берём отладчик в руки и останавливаемся на команде включения таймера. Непосредственно сразу перед её выполнением смотрим состояние всех регистров. Выход CH2 это функция от значения этих регистров. Тыкаем в отладчике значения и смотрим какой бит влияет на неправильное поведение.
- Реклама
так там и должна быть "1", исходно CNT < CCR =ARR/10. чего не так?
"110: PWM mode 1 (режим 1 ШИМ) - при счете вверх канал 1 активен (OC1REF=1), пока TIMx_CNT < TIMx_CCR1, иначе не активен (OC1REF=0). "
при включении TIM2->CCER |= TIM_CCER_CC2E;
состояние OCxREF отображается на ногу.
"110: PWM mode 1 (режим 1 ШИМ) - при счете вверх канал 1 активен (OC1REF=1), пока TIMx_CNT < TIMx_CCR1, иначе не активен (OC1REF=0). "
при включении TIM2->CCER |= TIM_CCER_CC2E;
состояние OCxREF отображается на ногу.
Здравствуйте! Подключаю дисплей ST7735 к 32L476. SPI1. Использую проверенную инициализацию. И он вроде запускается, рябь все дела. А залить не заливается.
Единственное что поменял кроме пинов - переключение 8 / 16 битовой передачи. Ибо до этого юзал 411 стм. Там было SPI2->CR1 &= ~SPI_CR1_DFF;
А в 476 нет DEF и вместо него я юзаю SPI1->CR1 &= ~SPI_CR1_CRCL;
Вроде синониумы. Еще грешу на пины дисплея TP0 & TP1 они у меня в воздухе. Подскажите пж, давно сношаюс
вот код инициализации и заливки

Ну и соответственно вызывается ини потом буффер
Единственное что поменял кроме пинов - переключение 8 / 16 битовой передачи. Ибо до этого юзал 411 стм. Там было SPI2->CR1 &= ~SPI_CR1_DFF;
А в 476 нет DEF и вместо него я юзаю SPI1->CR1 &= ~SPI_CR1_CRCL;
Вроде синониумы. Еще грешу на пины дисплея TP0 & TP1 они у меня в воздухе. Подскажите пж, давно сношаюс
вот код инициализации и заливки
Спойлер
Код: Выделить всё
void Send_CMD(uint8_t dat)
{
CS_LOY; //ChipSelect loy
DC_LOY; //DC LoyLevel
SPI1->CR1 &= ~SPI_CR1_CRCL;
while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = dat;
while (!(SPI1->SR & SPI_SR_TXE));
while ((SPI1->SR & SPI_SR_BSY));
CS_H; //ChipSelect Up
}
void Send_DAT(uint8_t dat){
CS_LOY; //ChipSelect loy
DC_H; //DC H
SPI1->CR1 &= ~SPI_CR1_CRCL;
while (!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = dat;
while (!(SPI1->SR & SPI_SR_TXE));
while ((SPI1->SR & SPI_SR_BSY));
CS_H;//ChipSelect Up
}
void Send_DAT16(uint16_t dat){
CS_LOY; //ChipSelect loy
DC_H; //DC H
SPI1->CR1 |= SPI_CR1_CRCL;
while (!(SPI1->SR & SPI_SR_TXE)){};
SPI1->DR = dat;
while (!(SPI1->SR & SPI_SR_TXE)){};
while ((SPI1->SR & SPI_SR_BSY)){};
CS_H;//ChipSelect Up
}
void LCD_Init()
{
CS_LOY; //ChipSelect loy
SPI1->CR1 |= SPI_CR1_SPE;//On Spi1
RST_H; //RST Hay
Delay(5);
RST_LOY; //RST loy
Delay(15);
RST_H; //RST Hay
Delay(15);
Send_CMD(0x01);//Sbros nastroek
Delay(35);
Send_CMD(ST77XX_SWRESET);
Delay(150);
Send_CMD(ST77XX_SLPOUT);
Delay(500);
Send_CMD(ST7735_FRMCTR1);
Send_DAT(0x01);
Send_DAT(0x2C);
Send_DAT(0x2D);
Send_CMD(ST7735_FRMCTR2);
Send_DAT(0x01);
Send_DAT(0x2C);
Send_DAT(0x2D);
Send_CMD(ST7735_FRMCTR3);
Send_DAT(0x01);
Send_DAT(0x2C);
Send_DAT(0x2D);
Send_DAT(0x01);
Send_DAT(0x2C);
Send_DAT(0x2D);
Send_CMD(ST7735_INVCTR);
Send_DAT(0x07);
Send_CMD(ST7735_PWCTR1);
Send_DAT(0xA2);
Send_DAT(0x02);
Send_DAT(0x84);
Send_CMD(ST7735_PWCTR2);
Send_DAT(0xC5);
Send_CMD(ST7735_PWCTR3);
Send_DAT(0x0A);
Send_DAT(0x00);
Send_CMD(ST7735_PWCTR4);
Send_DAT(0x8A);
Send_DAT(0x2A);
Send_CMD(ST7735_PWCTR5);
Send_DAT(0x8A);
Send_DAT(0xEE);
Send_CMD(ST7735_VMCTR1);
Send_DAT(0x0E);
Send_CMD(ST77XX_INVOFF);
Send_CMD(ST77XX_MADCTL);
Send_DAT(0xC0);
Send_CMD(ST77XX_COLMOD);
Send_DAT(0x05);
Send_CMD(ST7735_GMCTRP1);
Send_DAT(0x02);
Send_DAT(0x1C);
Send_DAT(0x07);
Send_DAT(0x12);
Send_DAT(0x37);
Send_DAT(0x32);
Send_DAT(0x29);
Send_DAT(0x2D);
Send_DAT(0x29);
Send_DAT(0x25);
Send_DAT(0x2B);
Send_DAT(0x39);
Send_DAT(0x00);
Send_DAT(0x01);
Send_DAT(0x03);
Send_DAT(0x10);
Send_CMD(ST7735_GMCTRN1);
Send_DAT(0x03);
Send_DAT(0x1D);
Send_DAT(0x07);
Send_DAT(0x06);
Send_DAT(0x2E);
Send_DAT(0x2C);
Send_DAT(0x29);
Send_DAT(0x2D);
Send_DAT(0x2E);
Send_DAT(0x2E);
Send_DAT(0x37);
Send_DAT(0x3F);
Send_DAT(0x00);
Send_DAT(0x00);
Send_DAT(0x02);
Send_DAT(0x10);
Send_CMD(ST77XX_NORON);
Delay(10);
Send_CMD(ST77XX_DISPON);
Delay(100);
CS_H;//ChipSelect Up
}
void SetWindow(uint16_t startX, uint16_t startY, uint16_t stopX, uint16_t stopY) {
Send_CMD(0x2A);
Send_DAT(0);
Send_DAT(startX);
Send_DAT(0);
Send_DAT(stopX);
Send_CMD(0x2B);
Send_DAT(0);
Send_DAT(startY);
Send_DAT(0);
Send_DAT(stopY);
}
void bufer()
{
uint16_t x = 0, y = 0;
SetWindow(10, 10, 128, 160);
Send_CMD(0x2C);
while(x++ <= 159)
{
y=0;
while(y++ <= 127)
{
Send_DAT16(0xFF00);//buf[128][160];
}
}
}
Ну и соответственно вызывается ини потом буффер
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
У L476 FIFO на SPI и команда SPI1->DR = dat; записывает два байта. Переделайте на байтовый доступ там где это надо.
- Реклама
Команды 8 битные передаются при стирании флага SPI1->CR1 &= ~SPI_CR1_CRCL;, а 16 битные при установке. Или я не то что то понял
- Сообщения: 457
- Зарегистрирован: Ср сен 02, 2015 07:47:20
[uquote="TEPEM",url="/forum/viewtopic.php?p=4552791#p4552791"]Команды 8 битные передаются при стирании флага SPI1->CR1 &= ~SPI_CR1_CRCL;, а 16 битные при установке. Или я не то что то понял[/uquote]
Нужно ещё и обращение к порту на 8 бит переделать.
*((__IO uint8_t *)&SPI1->DR) = dat;
И сам dat сделать uint8_t.
Нужно ещё и обращение к порту на 8 бит переделать.
*((__IO uint8_t *)&SPI1->DR) = dat;
И сам dat сделать uint8_t.
[uquote="HardWareMan",url="/forum/viewtopic.php?p=4552794#p4552794"][uquote="TEPEM",url="/forum/viewtopic.php?p=4552791#p4552791"]Команды 8 битные передаются при стирании флага SPI1->CR1 &= ~SPI_CR1_CRCL;, а 16 битные при установке. Или я не то что то понял[/uquote]
Нужно ещё и обращение к порту на 8 бит переделать.
*((__IO uint8_t *)&SPI1->DR) = dat;
И сам dat сделать uint8_t.[/uquote]
Там uint8_t стоит dat.
Заработало. Но не понятно почему. Там написано в рефе по умолчанию CRCL не записан что соответствует 8 бит. я его еще и стираю на всякий. Почему не работало без вообще не понятно. инициализация же работала
Нужно ещё и обращение к порту на 8 бит переделать.
*((__IO uint8_t *)&SPI1->DR) = dat;
И сам dat сделать uint8_t.[/uquote]
Там uint8_t стоит dat.
Заработало. Но не понятно почему. Там написано в рефе по умолчанию CRCL не записан что соответствует 8 бит. я его еще и стираю на всякий. Почему не работало без
Код: Выделить всё
*((__IO uint8_t *)&SPI1->DR) = dat;- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
1. Читайте RM, там всё есть
2. Посмотрите ассемблерный листинг обоих вариантов и всё поймёте.
3. Разрядность dat вообще не причём.
Спойлер
3. Разрядность dat вообще не причём.
Спасибо вам большое ребята! Очень выручили а то я уже нос повесил.
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
TEPEM, предлагаю слегка облагородить инициализацию. Ссылка на Compiler Explorer.
Ещё и размер кода уменьшится.
Спойлер
- Сообщения: 457
- Зарегистрирован: Ср сен 02, 2015 07:47:20
VladislavS, можно же просто оформить значения инита в массив констант и оттуда в цикле вычитывать. Зачем эти пляски с объектами?
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
[uquote="HardWareMan",url="/forum/viewtopic.php?p=4553000#p4553000"]VladislavS, можно же просто оформить значения инита в массив констант и оттуда в цикле вычитывать.[/uquote]Собственно так и сделано. Только более современными средствами.
[uquote="HardWareMan",url="/forum/viewtopic.php?p=4553000#p4553000"]Зачем эти пляски с объектами?[/uquote]Где вы там объекты увидели? Покажите хоть один.
PS: Насчёт зачем. Я смею утверждать, что этот код лучше оптимизируется компилятором.
[uquote="HardWareMan",url="/forum/viewtopic.php?p=4553000#p4553000"]Зачем эти пляски с объектами?[/uquote]Где вы там объекты увидели? Покажите хоть один.
PS: Насчёт зачем. Я смею утверждать, что этот код лучше оптимизируется компилятором.
- Сообщения: 457
- Зарегистрирован: Ср сен 02, 2015 07:47:20
[uquote="VladislavS",url="/forum/viewtopic.php?p=4553004#p4553004"]Где вы там объекты увидели? Покажите хоть один.
PS: Насчёт зачем. Я смею утверждать, что этот код лучше оптимизируется компилятором.[/uquote]
По ошибке бегло зацепился за токен class и обращение к членам. А потом уже увидел структуру. Ну да, так тоже можно, но я не уверен, что такая погоня за универсальностью (и удобством для человека) будет более оптимальным решением. Ну да ладно, решение достаточно изящно.
PS: Насчёт зачем. Я смею утверждать, что этот код лучше оптимизируется компилятором.[/uquote]
По ошибке бегло зацепился за токен class и обращение к членам. А потом уже увидел структуру. Ну да, так тоже можно, но я не уверен, что такая погоня за универсальностью (и удобством для человека) будет более оптимальным решением. Ну да ладно, решение достаточно изящно.
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
[uquote="HardWareMan",url="/forum/viewtopic.php?p=4553264#p4553264"]но я не уверен, что такая погоня за универсальностью (и удобством для человека) будет более оптимальным решением.[/uquote]Поверьте, компилятор лучше программиста знает как по массиву ходить. Впрочем, это легко проверяется. Ссылка на Compiler Explorer.
Пишем алгоритм обхода массива двумя способами.
И видим, что начхал компилятор на счётчик цикла и сгенерировал одинаковый бит в бит код для обоих вариантов.

Пишем алгоритм обхода массива двумя способами.
Спойлер
Спойлер
- Сообщения: 457
- Зарегистрирован: Ср сен 02, 2015 07:47:20
[uquote="VladislavS",url="/forum/viewtopic.php?p=4553350#p4553350"][uquote="HardWareMan",url="/forum/viewtopic.php?p=4553264#p4553264"]но я не уверен, что такая погоня за универсальностью (и удобством для человека) будет более оптимальным решением.[/uquote]Поверьте, компилятор лучше программиста знает как по массиву ходить. Впрочем, это легко проверяется.[/uquote]
Это хорошо, что x86/x64 компилеры последние 25 лет не стояли на месте. Но что там под РУКУ? Топик же не про x86/x64. Что там с тулчейнами под РУКУ?
Это хорошо, что x86/x64 компилеры последние 25 лет не стояли на месте. Но что там под РУКУ? Топик же не про x86/x64. Что там с тулчейнами под РУКУ?
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
x86 выбран только чтобы показать результат выполнения кода в Compiler Explorer. Для ARM компиляторы ни разу не отстают.
Добрый день! Это больше похоже на плюсы, сейчас попробую разобратся, совсем сложно пока для меня, но я стараюсь)
У меня все работает, кроме цветов. Вот фон один и тот же сзади 411 на дисплей выводит доски а с переди 476 кляксы вывел какие то. И что интересно вообще не понятно почему так может быть. Дисплеи одного класса(((
У меня белый это черный, черный это белый а красный синий ппц(((
В дисплее включал инверсию - не то(
Скорее всего дело в передаче выходит
Я попробовал по анологии но не помогло)
а так похожи цвета, но все равно где то близко
Пробовал цвет разбирать на ргб и менять местами, лажа какая то(((
Методом научного тыка добилсяя того что INVON + BGR режимы дисплея плюс перестановка битов при отправке дают нужные цвета
У меня все работает, кроме цветов. Вот фон один и тот же сзади 411 на дисплей выводит доски а с переди 476 кляксы вывел какие то. И что интересно вообще не понятно почему так может быть. Дисплеи одного класса(((
У меня белый это черный, черный это белый а красный синий ппц(((
В дисплее включал инверсию - не то(
Скорее всего дело в передаче выходит
Код: Выделить всё
void Send_DAT16(uint16_t dat){
CS_LOY; //ChipSelect loy
DC_H; //DC H
SPI1->CR1 |= SPI_CR1_CRCL;
while (!(SPI1->SR & SPI_SR_TXE)){};
SPI1->DR = dat;
while (!(SPI1->SR & SPI_SR_TXE)){};
while ((SPI1->SR & SPI_SR_BSY)){};
CS_H;//ChipSelect Up
}Код: Выделить всё
*((__IO uint16_t *)&SPI1->DR) = dat;Код: Выделить всё
void Send_DAT16(uint16_t dat){
uint8_t bytes[2];
bytes[0] = dat >> 8; // high byte (0x12)
bytes[1] = dat & 0x00FF; // low byte (0x34)
Send_DAT(bytes[0]);
Send_DAT(bytes[1]);
}
Методом научного тыка добилсяя того что INVON + BGR режимы дисплея плюс перестановка битов при отправке дают нужные цвета
- Сообщения: 2567
- Зарегистрирован: Вт май 01, 2018 19:44:47
TEPEM, не знаю надо ли это для вашего индикатора, но если нужно переставить местами два байта в uint16_t, то в Cortecx-M4 можно вот так сделать.
Это одна ассемблерная команда.
Код: Выделить всё
SPI1->DR = __REV16(dat);- Сообщения: 457
- Зарегистрирован: Ср сен 02, 2015 07:47:20
[uquote="VladislavS",url="/forum/viewtopic.php?p=4553488#p4553488"]TEPEM, не знаю надо ли это для вашего индикатора, но если нужно переставить местами два байта в uint16_t, то в Cortecx-M4 можно вот так сделать.
Это одна ассемблерная команда.[/uquote]
Это несколько ассемблерных команд. Следует уточнять, что это именно своп байтов в каждом полуслове REV16 - одна атомарная команда. /душнила: офф
Код: Выделить всё
SPI1->DR = __REV16(dat);Это несколько ассемблерных команд. Следует уточнять, что это именно своп байтов в каждом полуслове REV16 - одна атомарная команда. /душнила: офф


