Микроконтроллеры STM32 - тонкости работы, отладочные платы

Кто любит RISC в жизни, заходим, не стесняемся.
tonyk
Это не хвост, это антенна
Сообщения: 1309
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение tonyk »

TEPEM писал(а):Есть три неприятные функции в хале, которые я пытаюсь заменить cmsis.
Если я правильно понял, ТС используется SPI для работы с W25Qxxx. Вот простейший вариант реализации доступа к этой микросхеме. Работает на STM32F4.
Спойлер

Код: Выделить всё

#define W25Q_GUARD  ( 40'000'000 )

////////////////////////////////////////////////////////////////////////////////

uint8
W25Q::SPI_exchange( uint8 _aByte )
{
    uint8
        tmp8;
    int32
        guard = W25Q_GUARD;

    while( ( spi -> SR & SPI_SR_RXNE ) && ( guard > 0 ) )
    {
        tmp8 = spi -> DR;
        guard--;
    };

    if( guard <= 0 )
    {
        theMemoryIsBad = true;

        #ifdef DEBUG
            log_printf
            (
                MsgCat::ERR,
                "FTP : W25Q : Memory is bad. Line %d.\n", __LINE__
            );
        #endif

        return( 0 );
    }

    *( volatile uint8 *)&( spi -> DR) = _aByte;

    guard = W25Q_GUARD;

    while( ( !( spi -> SR & SPI_SR_RXNE ) ) && ( guard > 0 ) )
    {
        guard--;
    }

    if( guard <= 0 )
    {
        theMemoryIsBad = true;

        #ifdef DEBUG
            log_printf
            (
                MsgCat::ERR,
                "FTP : W25Q : Memory is bad. Line %d.\n", __LINE__
            );
        #endif

        return( 0 );
    }

    tmp8 = *( volatile uint8*)&( spi -> DR );

    return( tmp8 );
}

////////////////////////////////////////////////////////////////////////////////

uint8
W25Q::SPI_readByte( void )
{
    if( theMemoryIsBad == true )
    {
        return( 0 );
    }

    return( SPI_exchange( 0 ) );
}

////////////////////////////////////////////////////////////////////////////////

uint16
W25Q::SPI_readBytes( uint8* _buff, uint16 _n )
{
    if( theMemoryIsBad == true )
    {
        return( 0 );
    }

    if( ( _buff == 0 ) || ( _n == 0 ) )
    {
        return( 0 );
    }

    uint16
        i = _n;

    while( i )
    {
        *_buff = SPI_readByte();
        _buff++;
        i--;

        if( isFault() )
        {
            return( 0 );
        }
    }

    return( _n );
}

////////////////////////////////////////////////////////////////////////////////

void
W25Q::SPI_writeByte( uint8 _aByte )
{
    if( theMemoryIsBad == true )
    {
        return;
    }

    SPI_exchange( _aByte );
}

////////////////////////////////////////////////////////////////////////////////

uint16
W25Q::SPI_writeBytes( uint8* _buff, uint16 _n )
{
    if( theMemoryIsBad == true )
    {
        return( 0 );
    }

    if( ( _buff == 0 ) || ( _n == 0 ) )
    {
        return( 0 );
    }

    uint16
        i = _n;

    while( i )
    {
         SPI_writeByte( *_buff );
        _buff++;
        i--;

        if( isFault() )
        {
            return( 0 );
        }
    }

    return( _n );
}

////////////////////////////////////////////////////////////////////////////////

bool
W25Q::isFault( void )
{
    return( theMemoryIsBad );
}

////////////////////////////////////////////////////////////////////////////////
На всякий случай настройка SPI под эту микруху.
Спойлер

Код: Выделить всё

...
    spi -> CR1 =
        ( 0  << SPI_CR1_BIDIMODE_Pos )  | // 15
        ( 0  << SPI_CR1_BIDIOE_Pos )    | // 14
        ( 0  << SPI_CR1_CRCEN_Pos )     | // 13
        ( 0  << SPI_CR1_CRCNEXT_Pos )   | // 12
        ( 0  << SPI_CR1_DFF_Pos )       | // 11
        ( 0  << SPI_CR1_RXONLY_Pos )    | // 10 Fullduplex
        ( 1  << SPI_CR1_SSM_Pos )       | //  9  Software slave management disabled
        ( 1  << SPI_CR1_SSI_Pos )       | //  8
        ( 0  << SPI_CR1_LSBFIRST_Pos )  | //  7 MSB передается первым
        ( 0  << SPI_CR1_SPE_Pos )       | //  6 Пока _не_ включаем SPI!
        ( br << SPI_CR1_BR_Pos )        | //  5..3 делитель шины для тактирования SPI;
        ( 1  << SPI_CR1_MSTR_Pos )      | //  2 Master
        ( 0  << SPI_CR1_CPOL_Pos )      | //  1 полярность тактового сигнала
        ( 0  << SPI_CR1_CPHA_Pos );       //  0 Фаза тактового сигнала

    spi -> CR2 = \
        ( 0 << SPI_CR2_TXEIE_Pos )      | // Tx buffer empty interrupt enable
        ( 0 << SPI_CR2_RXNEIE_Pos )     | // RX buffer not empty interrupt enable

        // This bit controls the generation of an interrupt when an error
        // condition occurs )(CRCERR, OVR, MODF in SPI mode, FRE in TI mode and
        // UDR, OVR, and FRE in I2S mode).
        ( 0 << SPI_CR2_ERRIE_Pos )      |
        ( 0 << SPI_CR2_FRF_Pos )        | // 0/1 - Motorola/TO mode
        ( 0 << SPI_CR2_SSOE_Pos )       | // SS output enable
        ( 0 << SPI_CR2_TXDMAEN_Pos )    | // Tx buffer DMA enable
        ( 0 << SPI_CR2_RXDMAEN_Pos );     // Rx buffer DMA enable

        spi -> CR1 |= ( 1  << SPI_CR1_SPE_Pos );
...
Аватара пользователя
TEPEM
Нашел транзистор. Понюхал.
Сообщения: 153
Зарегистрирован: Чт дек 05, 2019 16:28:11
Откуда: Самара

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение TEPEM »

Не, она у меня на борту и отлично работает уже второй год. Я радиомодуль прикручиваю. И вот осцилограмма странная
danone78
Встал на лапы
Сообщения: 82
Зарегистрирован: Вт фев 15, 2022 21:28:35

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение danone78 »

_
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение VladislavS »

Стандартный путь пойти на сайт производителя и посмотреть схему чем не устраивает?

Обычные линейные стабилизаторы это. А в каком месте маркировка не английском там? :)
Аватара пользователя
TEPEM
Нашел транзистор. Понюхал.
Сообщения: 153
Зарегистрирован: Чт дек 05, 2019 16:28:11
Откуда: Самара

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение TEPEM »

Владислав! Вся надежда на Вас как обычно) И снова здравствуйте)
TIM2_CH2 дает шим на hcpl3120 та на транзистор и тот на двигатель.
Вот такой код

Код: Выделить всё

 GPIOB->MODER |=  GPIO_MODER_MODER3_1;      
       GPIOB->PUPDR |=   GPIO_PUPDR_PUPD3_1;
       GPIOB->AFR[0] |= 0x00001000;//PB3 AF1 - TIM2_CH2  
        
        TIM2->CR1       |= TIM_CR1_ARPE; // buffer the ARR register (not esp useful in this example)                
        TIM2->PSC       = 96000000/1000000-1; // scale to 1us
        const int freq  = 800; // Hz
        TIM2->ARR       = 1000000/freq; // convert freq to counts. Auto Reload Register
        TIM2->CCR2      = TIM2->ARR/10; // Duty cycle 50% on Compare/Capture Register 2
        TIM2->CCMR1     |= TIM_CCMR1_OC2PE // Enable preload for channel 2
                        | (0b110 << TIM_CCMR1_OC2M_Pos); // PWM mode 1                   
        TIM2->CCER      |= TIM_CCER_CC2E; // Enable Capture Compare for channel 2
        TIM2->EGR       |= TIM_EGR_UG;
Кнопочка там делает TIM2->CR1 |= TIM_CR1_CEN; и все работает.
Но есть одно огромное НО. Запуск при подаче питания на плату, с порта вылетает +3в. ИБП не расчитан на прямое включение, оффает сразу от такого подката. Да и фиг бы с ним. Но и движку крутится не надо без кнопки. Ни какие танцы с бубном вокруг подтяжки порта не чего не дают. Более того только выключение 2го канала таймера избавляет от этого плевка в начале, но стоит его включиить и шим начинается с этого плевка. Я уже хз что делать хоть дополнительный ключ ставить в схему управления драйвером. Выручайте пж
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение VladislavS »

Берём отладчик в руки и останавливаемся на команде включения таймера. Непосредственно сразу перед её выполнением смотрим состояние всех регистров. Выход CH2 это функция от значения этих регистров. Тыкаем в отладчике значения и смотрим какой бит влияет на неправильное поведение.
a797945
Мучитель микросхем
Сообщения: 446
Зарегистрирован: Вс ноя 01, 2015 09:15:16
Откуда: 69.Ржев

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение a797945 »

так там и должна быть "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 отображается на ногу.
Аватара пользователя
TEPEM
Нашел транзистор. Понюхал.
Сообщения: 153
Зарегистрирован: Чт дек 05, 2019 16:28:11
Откуда: Самара

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение TEPEM »

Просто сделал програмный шим.
Martian
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32
Контактная информация:

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение Martian »

Правильно, долой всю аппаратную периферию... :))) :facepalm:
Аватара пользователя
TEPEM
Нашел транзистор. Понюхал.
Сообщения: 153
Зарегистрирован: Чт дек 05, 2019 16:28:11
Откуда: Самара

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение TEPEM »

Здравствуйте! Подключаю дисплей ST7735 к 32L476. SPI1. Использую проверенную инициализацию. И он вроде запускается, рябь все дела. А залить не заливается.
Единственное что поменял кроме пинов - переключение 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];
          }
        }
}
Изображение

Ну и соответственно вызывается ини потом буффер
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение VladislavS »

У L476 FIFO на SPI и команда SPI1->DR = dat; записывает два байта. Переделайте на байтовый доступ там где это надо.
Аватара пользователя
TEPEM
Нашел транзистор. Понюхал.
Сообщения: 153
Зарегистрирован: Чт дек 05, 2019 16:28:11
Откуда: Самара

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение TEPEM »

Команды 8 битные передаются при стирании флага SPI1->CR1 &= ~SPI_CR1_CRCL;, а 16 битные при установке. Или я не то что то понял
Аватара пользователя
HardWareMan
Мучитель микросхем
Сообщения: 431
Зарегистрирован: Ср сен 02, 2015 07:47:20

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение HardWareMan »

[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.
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Аватара пользователя
TEPEM
Нашел транзистор. Понюхал.
Сообщения: 153
Зарегистрирован: Чт дек 05, 2019 16:28:11
Откуда: Самара

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение TEPEM »

[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 бит. я его еще и стираю на всякий. Почему не работало без

Код: Выделить всё

*((__IO uint8_t *)&SPI1->DR)  = dat;
вообще не понятно. инициализация же работала
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение VladislavS »

1. Читайте RM, там всё есть
СпойлерИзображение
изображение_2024-03-07_223300122.png
(37.39 КБ) 389 скачиваний
2. Посмотрите ассемблерный листинг обоих вариантов и всё поймёте.
3. Разрядность dat вообще не причём.
Аватара пользователя
TEPEM
Нашел транзистор. Понюхал.
Сообщения: 153
Зарегистрирован: Чт дек 05, 2019 16:28:11
Откуда: Самара

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение TEPEM »

Спасибо вам большое ребята! Очень выручили а то я уже нос повесил.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение VladislavS »

TEPEM, предлагаю слегка облагородить инициализацию. Ссылка на Compiler Explorer.
СпойлерИзображение
изображение_2024-03-08_095816011.png
(45.49 КБ) 406 скачиваний
Ещё и размер кода уменьшится.
Аватара пользователя
HardWareMan
Мучитель микросхем
Сообщения: 431
Зарегистрирован: Ср сен 02, 2015 07:47:20

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение HardWareMan »

VladislavS, можно же просто оформить значения инита в массив констант и оттуда в цикле вычитывать. Зачем эти пляски с объектами?
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение VladislavS »

[uquote="HardWareMan",url="/forum/viewtopic.php?p=4553000#p4553000"]VladislavS, можно же просто оформить значения инита в массив констант и оттуда в цикле вычитывать.[/uquote]Собственно так и сделано. Только более современными средствами.

[uquote="HardWareMan",url="/forum/viewtopic.php?p=4553000#p4553000"]Зачем эти пляски с объектами?[/uquote]Где вы там объекты увидели? Покажите хоть один.

PS: Насчёт зачем. Я смею утверждать, что этот код лучше оптимизируется компилятором.
Аватара пользователя
HardWareMan
Мучитель микросхем
Сообщения: 431
Зарегистрирован: Ср сен 02, 2015 07:47:20

Re: Микроконтроллеры STM32 - тонкости работы, отладочные пла

Сообщение HardWareMan »

[uquote="VladislavS",url="/forum/viewtopic.php?p=4553004#p4553004"]Где вы там объекты увидели? Покажите хоть один.

PS: Насчёт зачем. Я смею утверждать, что этот код лучше оптимизируется компилятором.[/uquote]
По ошибке бегло зацепился за токен class и обращение к членам. А потом уже увидел структуру. Ну да, так тоже можно, но я не уверен, что такая погоня за универсальностью (и удобством для человека) будет более оптимальным решением. Ну да ладно, решение достаточно изящно.
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Ответить

Вернуться в «ARM»