/* Private includes ----------------------------------------------------------*/
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stm32f1xx.h>
//#include <stm32f1xx_it.h>
//#include <stm32f1xx_hal.h>
//#include <stm32f10x.h>
//#include <stm32f10x_rcc.h>
//#include <stm32f10x_gpio.h>
static volatile uint32_t ms_ticks = 0;
static volatile bool tick_1ms_elapsed = 0;
static volatile bool tick_1000ms_elapsed = 0;
unsigned long mycnt1;
float myflt1;
char Rx_data[10]; // creating a buffer of 10 bytes
uint8_t rec_length = 0;
char buffer[32] = {0};
uint8_t len = 0;
char rxbuff[32];
/* Private function prototypes -----------------------------------------------*/
static void init_clock(void);
void SysTick_Handler(void);
void gpio_config(void);
void uart1_config(void);
void uart1_write_char(int ch);
void uart1_write_string(char *p);
char uart1_read_char(void);
void mydelay(uint32_t time);
int readMsg(void);
/* START OF MAIN -----------------------------------------------------*/
int main (void)
{
init_clock();
if (SysTick_Config(SystemCoreClock / 1000))
{ // Configure the SysTick timer to overflow every 1 ms, use 1000000 for 1 us
while (1); // no error must happen here, otherwise this board is dead
}
asm volatile ("nop");
gpio_config ();
asm volatile ("nop");
uart1_config ();
sprintf(buffer, "SystemCoreClock: %ld\n\n", SystemCoreClock);
uart1_write_string(buffer);
asm volatile ("nop");
while (1)
{
asm volatile ("nop");
if (tick_1ms_elapsed)
{
//... Do something every ms
tick_1ms_elapsed = 0; // Reset the flag (signal 'handled')
}
if (tick_1000ms_elapsed) //... Do something every second
{
GPIOC->BSRR |= GPIO_BSRR_BS14; //Turn ON the LED on PC14
mycnt1++;
sprintf(buffer, "ON for %08ld sec.\n", mycnt1);
uart1_write_string(buffer);
// printf("%5.1f\n", myflt1);
// myflt1 += 0.1;
tick_1000ms_elapsed = 0; // Reset the flag (signal 'handled')
GPIOC->BSRR |= GPIO_BSRR_BR14; //Turn OFF the LED on PC14
}
/***
if (USART1->SR & USART_SR_RXNE) //if RX is not empty
{
char temp = USART1->DR; //fetch the data received
USART1->DR = temp; //send it back out
while (!(USART1->SR & USART_SR_TC)) //wait for TX to be complete
;
}
***/
// uint8_t data = uart1_read_char();
// uart1_write_char(data);
// readMsg();
//this part just send back to the HTerm console - the same text as received
if (len != 0)
{
for (int i=0; i<len+1; i++)
{
USART1->DR = rxbuff[i];
while(!(USART1->SR & USART_SR_TXE)); //TXE becomes true (1) when the content of DR (data register) goes into shift register
}
len = 0;
}
// mydelay (100000000);
}
}
/* END OF MAIN -----------------------------------------------------*/
/* START OF PRIVATES -----------------------------------------------*/
/**
* @brief Configure and initialise clock for SysCLK of 72 MHz
*
*/
void init_clock(void)
{
/*****
source:
https://medium.com/@csrohit/clock-configuration-in-stm32-6a058da220e0
Using the above steps, we have successfully set the clocks as follows
HCLK to 72MHz
SYSCLK to72MHz
AHBCLK to 72MHz
APB1CLK to 36MHz
APB2CLK to 72MHz
In the demo application for this article, this clock@72MHz is used to drive
the SysTick timer which in turn is used as a timebase for the aplication.
*****/
FLASH->ACR |= FLASH_ACR_LATENCY_2; // Two wait states, per datasheet
RCC->CFGR |= RCC_CFGR_PPRE1_2; // prescale AHB1 = HCLK/2
RCC->CFGR |= RCC_CFGR_PLLXTPRE_HSE; // PREDIV1 = 0
RCC->CR |= RCC_CR_HSEON; // enable HSE clock
while (!(RCC->CR & RCC_CR_HSERDY)); // wait for the HSEREADY flag
RCC->CFGR |= RCC_CFGR_PLLSRC; // set PLL source to HSE
RCC->CFGR |= RCC_CFGR_PLLMULL9; // multiply by 9
RCC->CR |= RCC_CR_PLLON; // enable the PLL
while (!(RCC->CR & RCC_CR_PLLRDY)); // wait for the PLLRDY flag
RCC->CFGR |= RCC_CFGR_SW_PLL; // set clock source to PLL
while (!(RCC->CFGR & RCC_CFGR_SWS_PLL));// wait for PLL to be CLK
SystemCoreClockUpdate(); // calculate the SYSCLOCK value
}
//! The interrupt handler for the SysTick module
void SysTick_Handler(void)
{
// HAL_IncTick();
ms_ticks++;
tick_1ms_elapsed = 1;
if (ms_ticks % 1000 == 0)
{
tick_1000ms_elapsed = 1;
}
}
void gpio_config (void)
{
asm volatile ("nop");
//PC13 as output
GPIOC->CRH &= ~(GPIO_CRH_MODE13 | GPIO_CRH_CNF13); //Clear MODE13 and CNF13 fields
GPIOC->CRH |= GPIO_CRH_MODE13_1 | GPIO_CRH_MODE13_0; //Set MODE13 to 3 (Output)
//PC14 as output
GPIOC->CRH &= ~(GPIO_CRH_MODE14 | GPIO_CRH_CNF14); //Clear MODE14 and CNF14 fields
GPIOC->CRH |= GPIO_CRH_MODE14_1 | GPIO_CRH_MODE14_0; //Set MODE14 to 3 (Output)
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; //Enable GPIOC CLOCK
}
void uart1_config (void)
{
/*********************************************
USART1 TX on STM32 is at pin A9, RX is at pin
A10. Use pinout, or CubeMX to find those two
pins.
==========STM32===========FTDI================
GND------------GND pin
pin A9 TX-------------RX pin
pin A10 RX-------------TX pin
*********************************************/
//Enable the UART CLOCK and GPIO CLOCK
//USART1 / GPIOA clock enable / enabling pin A9 for alternating funct. for uart/usart
RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN;
//remaping if needed
//AFIO->MAPR |= AFIO_MAPR_USART1_REMAP ; //remap RX TX to PB7 PB6
//pin configurations: PA9- TX is set to ALternate-push-pull and 50MHz
GPIOA->CRH |= GPIO_CRH_MODE9 | GPIO_CRH_CNF9_1;
GPIOA->CRH &= ~(GPIO_CRH_CNF9_0);
GPIOA->CRH |= GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9_0 | GPIO_CRH_MODE9_1; //port A9
GPIOA->CRH &= ~(GPIO_CRH_CNF9_0); //port A9 is TX pin
GPIOA->CRH &= ~(GPIO_CRH_MODE10_0 | GPIO_CRH_MODE10_1); //port A10 is RX pin
GPIOA->CRH |= GPIO_CRH_CNF10_0; //port A10 is RX pin
//Program the M bit in USART_CR1 to define the word length.
// USART2->CR1 &= ~(1<<12); // M =0; 8 bit word length
//Select the desired baud rate using the USART_BRR register.
// USART1->BRR = RCC_APB2_FREQ / 115200;
//clkPer/(baudRx_16bit)=72MHZ/9600 = 7500 = 0x1D4C
/* Remove comment line for speed that you want to use*/
//USART1->BRR = (0xEA60); // 1200 Baud
//USART1->BRR = (0x7530); // 2400 Baud
//USART1->BRR = (0x3A98); // 4800 Baud
USART1->BRR = (0x1D4C); // 9600 Baud
//USART1->BRR = (0x1388); // 14400 Baud
//USART1->BRR = (0xEA6) ; // 19200 Baud
//USART1->BRR = (0x9c4) ; // 28800 Baud
//USART1->BRR = (0x753) ; // 38400 Baud
//USART1->BRR = (0x505) ; // 56000 Baud
//USART1->BRR = (0x4E2) ; // 57600 Baud
//USART1->BRR = (0x271) ; // 115200 Baud
//USART1->BRR = (0x232) ; // 128000 Baud
//USART1->BRR = (0x119) ; // 256000 Baud
//USART1->BRR = (0x8C) ; // 512000 Baud
//USART1->BRR = (0x46) ; // 1024000 Baud
//USART1->BRR = (0x23) ; // 2048000 Baud
//USART1->BRR = (0x18) ; // 3000000 Baud (3 MHz, max speed that HTerm can get, non-standard speed)
// USART1 -> CR2 |= USART_CR2_CLKEN;
//----- USART INT bits -----
USART1->CR1 |= USART_CR1_RXNEIE; //enable RXNE interrupt
// USART1->CR1 |= USART_CR1_TXEIE; //enable TXE interrupt
// USART1->CR1 |= USART_CR1_TCIE; //enable TC interrupt
// USART1->CR1 |= USART_CR1_IDLEIE; //enable IDLE interrupt
USART1->CR1 |= USART_CR1_TE; //transmitter enable
USART1->CR1 |= USART_CR1_RE; //receiver enable
USART1->CR1 |= USART_CR1_UE; //usart enable
NVIC_EnableIRQ(USART1_IRQn); //ENABLE interrupt for USART1 on NVIC
}
/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
/***
//info:
//https://github.com/ceremcem/modbus_example/tree/master/Src
//https://stackoverflow.com/questions/46198829/stm32-hal-usart-receive-by-interrupt
if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE))
{
__HAL_UART_CLEAR_IDLEFLAG(&huart2); // taken from https://electronics.stackexchange.com/questions/471272/setting-up-stm32-timer-for-uart-idle-detection#comment1353999_480556
uart2_idleHandler();
}
else
{
uart2_dataHandler();
}
return;
// HAL_UART_IRQHandler(&huart2);
***/
//check if we are here because of RXNE interrupt
if (USART1->SR & USART_SR_RXNE) //if RX is not empty
{
GPIOC->BSRR |= GPIO_BSRR_BS13; //Turn ON the LED on PC13
char temp = USART1->DR; //fetch the received data
USART1->DR = temp; //send it back out
while (!(USART1->SR & USART_SR_TC));
}
//check if we are here because of TXEIE interrupt
// if (USART1->SR & USART_SR_TC)
if (USART1->SR & USART_SR_TXE)
{
//handle transmit completion here
GPIOC->BSRR |= GPIO_BSRR_BS13; //Turn ON the LED on PC13
}
GPIOC->BSRR |= GPIO_BSRR_BR13; //Turn OFF the LED on PC13
}
void uart1_dataHandler(void)
{
volatile char buff;
// HAL_UART_Receive(&huart2, (uint8_t *)&buff, 1, 100);
// HAL_UART_Receive(&huart2, (uint8_t *)&buff, 1, 100);
// Rx_data[rec_length] = buff;
// if(rec_length++ > 9) rec_length = 0;
// HAL_UART_Transmit(&huart2, "d", 1, 100);
}
int readMsg(void)
{
for(len=0; len<32; len++)
{
// if(USART1->CR1 & (1 << USART1_SR_RXNE))
// {
while((USART1->SR & USART_SR_RXNE) == 0)
{
GPIOC->BSRR |= GPIO_BSRR_BS13; //Turn ON the LED on PC13
}
rxbuff[len]= USART1->DR;
if (rxbuff[len]==10 || rxbuff[len]==13) break; //if enter is pressed, providing that it is 10 or 0xA (line feed), or 13 (0xD) (carriage return)
// }
}
GPIOC->BSRR |= GPIO_BSRR_BR13; //Turn OFF the LED on PC13
return len; //just returning number of entered characters, not including line feed nor carriage return (!)
}
char uart1_read_char(void)
{
/*********** STEPS FOLLOWED *************
1. Wait for the RXNE bit to set. It indicates that the data has been received and can be read.
2. Read the data from USART_DR Register. This also clears the RXNE bit
****************************************/
uint8_t temp;
/*Make sure the receive data register is not empty*/
while((USART1 ->SR & USART_SR_RXNE) == 0);
// if(USART1->CR1 & (1 << USART1_SR_RXNE))
// {
temp = (USART1->DR & 0xff); // Read the data. This clears the RXNE also
return temp;
// }
// return USART1->DR; // //Read data
}
void uart1_write_char(int ch)
{
/*********** STEPS FOLLOWED *************
1. wait until TC=1.
This indicates that the transmission of the last frame is complete.
This is required for instance when the USART is disabled or enters the Halt mode
to avoid corrupting the last transmission.
2. Write the data to send in the USART_DR register (this clears the TXE bit).
Repeat this for each data to be transmitted in case of single buffer.
****************************************/
//source: https://blog.embeddedexpert.io/?p=386
/*Make sure the transmit data register is empty*/
while(!(USART1->SR & USART_SR_TXE));
/*Write to transmit data register*/
USART1->DR = (ch & 0xff);
// USART1 -> CR1 |= USART_CR1_SBK;
// while((USART1->SR & USART_SR_TC) == 0);
}
void uart1_write_string(char *p)
{ //source: https://blog.embeddedexpert.io/?p=386
while(*p != '\0')
{
uart1_write_char(*p);
p++;
}
}
void mydelay(uint32_t time)
{
while (time--);
}
Loading
stm32-bluepill
stm32-bluepill