2024-11-27 09:14 AM
Hi,
I am learning and exploring the STM32F756VGH6. My goal is to setup a simple UART and send some data to the PC using USB-UART serial converter and puTTy terminal on PC. I am using register based coding approach as it makes the code more efficient. However, the code provided down bellow (that I have written) is faulty. I strongly suspect the problem lies somewhere in my UART setup function (but I could not figure out where exactly), because if I omit it, main loops gets executed (it does not even jam in the UART_Send function even though the UART has not been initialized) and I see the background leds blinking. If I try to execute the UART setup function, the led turns on and it stays like that indefinitely, needless to say I do not get any signals on my TX/RX lines, those always stay at high level (I have checked it with a logic analyzer). Both TX/RX lines have a 5.1k pullups to +3.3V. I have written some simple codes for my current setup and it worked fine, so hardware issue is very unlikely. Any ideas to get this code moving? Thank you in advance.
#include "main.h"
void Core_Clock_Setup (void){
RCC->CR |= RCC_CR_HSEON; //Set the clock source to external crystal/resonator (HSE)
while (!(RCC->CR & RCC_CR_HSEON)); //Wait until clock gets stable
RCC->APB1ENR |= RCC_APB1ENR_PWREN; //Enable power interface clock
PWR->CR1 &= ~(1U << 14);
PWR->CR1 &= ~(1U << 15); //Set internal voltage regulator to is reset value (scale 1)
FLASH->ACR &= ~FLASH_ACR_ARTEN; //Disable ART accelerator
FLASH->ACR &= ~FLASH_ACR_ARTRST; //Reset ART accelerator
FLASH->ACR |= FLASH_ACR_PRFTEN; //Enable prefetch
FLASH->ACR |= FLASH_ACR_LATENCY_6WS; //Set 7 CPU clock cycle flash memory access time (in order to get 200 MHz core clock)
//@ 25 MHz crystal, 200 MHz core clock configuration down below
RCC->CFGR &= ~(((1 << (7 - 4 + 1)) - 1) << 4);
RCC->CFGR &= ~(1 << 4); //Core clock division by 1 (core clock is not devided)
RCC->CFGR &= ~(1 << 5);
RCC->CFGR &= ~(1 << 6);
RCC->CFGR &= ~(1 << 7);
RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC_HSE;//HSE is set to be PLL entry
RCC->PLLCFGR &= ~(1 << 16); //PLLP Setting corresponding PLL prescalers (division by 2)
RCC->PLLCFGR &= ~(1 << 17);
RCC->PLLCFGR &= ~((1 << 6) - 1);
RCC->PLLCFGR |= (16 & ((1 << 6) - 1)); //PLLM Setting corresponding PLL prescalers (division by 16)
//RCC->PLLCFGR |= (16 << 0);
RCC->PLLCFGR &= ~(((1 << (14 - 6 + 1)) - 1) << 6);
RCC->PLLCFGR |= (256 << 6); //PLLN Setting corresponding PLL prescalers ( multiplication by 256)
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; //APB1 Low speed prescaler of 4 (50 MHz, max is 54 Mhz)
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; //APB2 High speed prescaler of 2 (100 MHz, max is 108 Mhz)
RCC->CR |= RCC_CR_PLLON; //Enable PLL
while (!(RCC->CR & RCC_CR_PLLRDY)); //Wait until PLL gets stable
RCC->CFGR |= RCC_CFGR_SW_PLL; //PLL is set to be core clock
//RCC->CFGR |= RCC_CFGR_SW_HSE; //HSE is set to be core clock
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // Wait until PLL indeed becomes core clock source
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
void Timer1_Setup(void){ //16 bit advanced timer
RCC->DCKCFGR1 &= ~ (1 << 24); //TIMxCLK = 2xPCLKx
//When TIMPRE bit of the RCC_DCKCFGR1 register is reset, if APBx prescaler is 1, then TIMxCLK = PCLKx, otherwise
//TIMxCLK = 2x PCLKx.
// When TIMPRE bit in the RCC_DCKCFGR1 register is set, if APBx prescaler is 1,2 or 4, then TIMxCLK = HCLK, otherwise
//TIMxCLK = 4x PCLKx.
//TIM1 CLK is HCLK in this case
RCC->APB2ENR |= (1 << 0); //Enable Timer 1 clock
TIM1->PSC = 99; //APB1 is 50 Mhz and 100 MHZ for timer (The number is set: Clock in MHz - 1) 1 full period equals 1 MHZ
TIM1->ARR = 0xFFFF; //Auto reload at 100 ticks -> around 100 micro seconds at 100 MHz timer clock
TIM1->CR1 |= (1 << 0); //Enable Timer 1 counter
while(!(TIM1->SR & (1<<0))); //Wait until timer update bit is set
}
void delay_ms (uint16_t ms){
TIM1->CR1 = (1 << 0);
for(uint16_t i = 0; i<ms; i++)
{
TIM1->CNT = 0; //Reset counter
while (TIM1->CNT < 2000); //Wait until counter reaches desired value
}
TIM1->CR1 &= ~(1 << 0);
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void GPIO_Setup(void){
//PC14 OUTPUT //LEDS
RCC->AHB1ENR |= (1 << 2); //Enable clock for GPIO bank C
RCC->AHB1ENR |= (1 << 4); //Enable clock for GPIO bank E
delay_ms(1);
GPIOC->MODER |= (0b01 << 28); //PC14 General purpose output mode
GPIOC->OTYPER &= ~ (1 << 14); //PC14 Output push-pull (reset state)
GPIOC->OSPEEDR |= (0b11 << 28); //PC14 very high GPIO speed
GPIOC->PUPDR |= (0b10 << 28); //PC14 pull down resistors
//PC15 OUTPUT
GPIOC->MODER |= (0b01 << 30); //PC15 General purpose output mode
GPIOC->OTYPER &= ~ (1 << 15); //PC15 Output push-pull (reset state)
GPIOC->OSPEEDR |= (0b11 << 30); //PC15 very high GPIO speed
GPIOC->PUPDR |= (0b10 << 30); //PC15 pull down resistors
//PE4 OUTPUT
GPIOE->MODER |= (0b01 << 8); //PE4 General purpose output mode
GPIOE->OTYPER &= ~ (1 << 4); //PE4 Output push-pull (reset state)
GPIOE->OSPEEDR |= (0b11 << 8); //PE4 very high GPIO speed
GPIOE->PUPDR |= (0b10 << 8); //PE4 pull down resistors
//PE0 OUTPUT
GPIOE->MODER |= (0b01 << 0); //PE0 General purpose output mode
GPIOE->OTYPER &= ~ (1 << 0); //PE0 Output push-pull (reset state)
GPIOE->OSPEEDR |= (0b11 << 0); //PE0 very high GPIO speed
GPIOE->PUPDR |= (0b10 << 0); //PE0 pull down resistors
//-----------------------------------------------------------------------------------
//PE5 INPUT ALL BUTTONS EXTERNALLY PULLED UP
GPIOE->MODER |= (0b00 << 10); //PE5 General purpose input mode
//PE6 INPUT
GPIOE->MODER |= (0b00 << 12); //PE6 General purpose input mode
}
void UART1_Setup(){
//RCC->APB2ENR = (1 << 4); //USART1 clock enabled
//TX1 at pin PA9 and RX1 at pin PA10
GPIOA->MODER = (0b10 << 18); //Assign alternate function of UART to pin PA9
GPIOA->MODER = (0b10 << 20); //Assign alternate function of UART to pin PA10
GPIOA->OSPEEDR = (0b11 << 18); //Highest speed at pin PA9
GPIOA->OSPEEDR = (0b11 << 20); //Highest speed at pin PA10
GPIOA->PUPDR = (0b00 << 18); //No pullup, no pulldown resistor on PA9
GPIOA->PUPDR = (0b00 << 20); //No pullup, no pulldown resistor on PA10
GPIOA->AFR[1] = (0b0111 << 4); //Select alternate function as UART on pin PA9
GPIOA->AFR[1] = (0b0111 << 8); //Select alternate function as UART on pin PA10
RCC->AHB1ENR |= (1 << 0); //Enable clock for GPIO bank A
USART1->CR1 = 0x00; //Reset register just in case
USART1->CR1 = (0b00 << 28); //M[1:0] = 00: 1 Start bit, 8 data bits, n stop bits
USART1->CR1 &= ~ (1 << 15); //Oversampling by 16
USART1->BRR = 0x6C8; //fclk/baud rate 200MHz / 115200
USART1->CR1 = (1 << 3); //Transmitter is enabled
USART1->CR1 = (1 << 2); //Receiver is enabled
RCC->APB2ENR = (1 << 4); //USART1 clock enabled
USART1->CR1 = (1 << 0); //USART enable
}
void UART1_Send(uint8_t character){
USART1->TDR = character; //Load data to transmit register
//while(!(USART1->ISR & (1 << 6))); //Wait until transmission is executed
}
uint8_t UART1_Receive (void){
uint8_t character;
while(!(USART1->ISR & (1 << 5))); //Wait receive buffer fills up
character = USART1->RDR; //Read the receive register
return character;
}
int main (void){
Core_Clock_Setup();
Timer1_Setup();
GPIO_Setup();
UART1_Setup();
GPIOC->BSRR = 0x4000;
GPIOC->BSRR = (1 << 30);
while(1){
GPIOC->BSRR = (1 << 15);
delay_ms(750);
UART1_Send('S');
GPIOC->BSRR = (1 << 31);
delay_ms(750);
UART1_Send('S');
}
}
2025-01-21 04:59 AM
@Vilius wrote:I am learning and exploring the STM32F756VGH6 ... I am using register based coding approach as it makes the code more efficient.
Apart from the fallacy already noted by @Tesla DeLorean, trying to optimise while learning is probably not a great approach.
As the famous saying goes,
"premature optimisation is a root of all kinds of evil"