diff --git a/ADC.c b/ADC.c new file mode 100644 index 0000000..bec72cc --- /dev/null +++ b/ADC.c @@ -0,0 +1,16 @@ +uint32_t SingleChannel(ADC_HandleTypeDef* hadc){ + HAL_ADC_Start(&hadc); + HAL_ADC_PollForConversion (hadc, 100); + uint32_t x = HAL_ADC_GetValue(hadc); + HAL_ADC_Stop(&hadc); + return x; +} + +void MultiChannel(ADC_HandleTypeDef *hadc, uint32_t *outbuffer, uint8_t n_of_channels){ + HAL_ADC_Start(hadc); + for(uint8_t i = 0; i 6){ + for(int i = 0; i= LCBADDRMIN && msgTxAddr <= LCBADDRMAX){ + isLCB = 1; + } + } + + uint8_t AAcount = 0; + for(int i = 0; i 6){ + payload = 1; + } + + if(msgCmd == SW_VER_ASK){ //verze sw //type 0 + TxParseMSG(huart,0,0x00,0x00,msgTxAddr); + } + else if(msgCmd == STATUS){ //stav (charging, off, on) //type 1 + uint8_t msgStatus = 0; + TxParseMSG(huart,1,0x00,msgStatus,msgTxAddr); + } + else if(msgCmd == STATE_ASK){ //status (err) //type 2 + uint8_t msgState = 0; + TxParseMSG(huart,2,0x00,msgState,msgTxAddr); + } +#ifdef ALINK_CTRL + else if(msgCmd == ALINK_STABLE_STATE && payload == 1){//zapnuti/vypnuti ustaleneho stavu, default je vyply + SteadyState = msgData[0]; + } + else if(msgCmd == ALINK_BLOCK_PLS && payload == 1){//vyber ktere pulsy blokovat, popis funkce je v @info + if(msgData[0] == 0x00){ + for(int i = 0; i < 8; i++){ + INJ0.PULSE_DEL_ARR[i] = msgData[1+i]; + } + } + else if(msgData[0] == 0x01){ + for(int i = 0; i < 8; i++){ + INJ1.PULSE_DEL_ARR[i] = msgData[1+i]; + } + } + else if(msgData[0] == 0x02){ + for(int i = 0; i < 8; i++){ + INJ2.PULSE_DEL_ARR[i] = msgData[1+i]; + } + } + else; + } + else if(msgCmd == ALINK_BLOCK_PLS_END && payload == 1){//vyber po ktere pulsy blokovat, popis funkce je v @info + if(msgData[0] == 0x00){ + for(int i = 0; i < 8; i++){ + INJ0.PULSE_DEL_END_ARR[i] = msgData[1+i]; + } + } + else if(msgData[0] == 0x01){ + for(int i = 0; i < 8; i++){ + INJ1.PULSE_DEL_END_ARR[i] = msgData[1+i]; + } + } + else if(msgData[0] == 0x02){ + for(int i = 0; i < 8; i++){ + INJ2.PULSE_DEL_END_ARR[i] = msgData[1+i]; + } + } + else; + } + else if(msgCmd == ALINK_FET_SW_PAUSE && payload == 1){//Nastaveni delky pauzy mezi prepinani fetu + int hi = msgData[1]; + int lo = msgData[2]; + int delay = (hi*256)+lo; + + if(msgData[0] == 0x00){ + INJ0.SWITCH_DELAY = SwitchDelaySetup(INJ0, delay); + } + else if(msgData[0] == 0x01){ + INJ1.SWITCH_DELAY = SwitchDelaySetup(INJ1, delay); + } + else if(msgData[0] == 0x02){ + INJ2.SWITCH_DELAY = SwitchDelaySetup(INJ2, delay); + } + else; + } + else if(msgCmd == ALINK_PULSE_BLK_TIM && payload == 1){//po kolika ms blokovat puls 2B + uint8_t hi = msgData[1]; + uint8_t lo = msgData[2]; + + float ARR = 65535; + float PSC = 53; + + float x = (1/(SysClk/APBDiv))*(PSC+1)*(ARR+1)*1000; + float us = (x/ARR)*1000; + int BlockPulseAfterMs = (hi*256)+lo; + int BlockPulseAfterTicks = BlockPulseAfterMs/us; + + if(msgData[0] == 0x00){ + INJ0.BLOCK_AFTER_TICKS = BlockPulseAfterTicks; + INJ0.BLOCK_AFTER_US = BlockPulseAfterMs; + } + else if(msgData[0] == 0x01){ + INJ1.BLOCK_AFTER_TICKS = BlockPulseAfterTicks; + INJ1.BLOCK_AFTER_US = BlockPulseAfterMs; + } + else if(msgData[0] == 0x02){ + INJ2.BLOCK_AFTER_TICKS = BlockPulseAfterTicks; + INJ2.BLOCK_AFTER_US = BlockPulseAfterMs; + } + else; + } +#ifdef ALINK_BRD_RST + else if(msgData[0] == ALINK_BRD_RST){ + TxParseMSG(huart,3,0x00,msgData[0],msgTxAddr); + HAL_NVIC_SystemReset(); + } +#endif + } +#endif + else; +} + +/** + * @brief Response message parser + * @param huart typedef + * @param type of message + * @param command + * @param data of message + * @param address of destination device + */ +void TxParseMSG(UART_HandleTypeDef *huart, int type, uint8_t CMD, uint8_t mess, uint8_t addr){ + uint8_t crc = 0; + int datasize = 0; + uint8_t data_buffer[40]; + uint8_t data_buffer_size = 0; + +//verze softwaru + if(type == 0){ + uint8_t data[] = {addr,0x0A,ADDRESS,CMD,VERSION,SUB_VERSION,RELEASE,BUGFIX}; + datasize = sizeof(data); + + for(int i = 0; i> 24; + data[14] = DATA_READ >> 16; + data[15] = DATA_READ >> 8; + data[16] = DATA_READ; + + for(int i = 0; iBSRR |= 1 << 0; +*/ + +//STM32F4 +void GPIO(GPIO_TypeDef* GPIOx, uint16_t pin, uint8_t state){ + if(state == 0){ + GPIOx->BSRR = (uint32_t)pin << 16U; + } + else{ + GPIOx->BSRR = pin; +} + +//STM32F0 +void GPIO(GPIO_TypeDef* GPIOx, uint16_t pin, uint8_t state){ + if(state == 0){ + GPIOx->BRR = pin; + } + else{ + GPIOx->BSRR = pin; +} \ No newline at end of file diff --git a/README.md b/README.md index 850610f..cd53497 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ -# STM32_Examples - -Example code for STM32 MCUs \ No newline at end of file +# STM32 Examples + +Examples for STM32 MCUs \ No newline at end of file diff --git a/STM_Flash.c b/STM_Flash.c new file mode 100644 index 0000000..c443726 --- /dev/null +++ b/STM_Flash.c @@ -0,0 +1,60 @@ +void Flash(uint32_t address, uint32_t data, uint16_t datasize, char operation){ + if(operation == 1){ + HAL_FLASH_Unlock(); + + EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; + EraseInitStruct.PageAddress = address; + EraseInitStruct.NbPages = 1U; + + if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK){ + Error_Handler(); + } + + addressNew = address; + + //while (Address < SECTOR_63){ + if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addressNew, data) == HAL_OK){ + addressNew = addressNew + 4; + } + else + { + Error_Handler(); + } + //} + + HAL_FLASH_Lock(); + + DATA_READ = *(__IO uint32_t*)addressNew; + + if(DATA_READ == data){ + GPIOA->BSRR = DE_Pin; + char msg[9] = {"Flash OK"}; + HAL_UART_Transmit(&huart2, (uint8_t *)&msg, sizeof(msg), 0xFFFF); + GPIOA->BRR = DE_Pin; + } + else{ + GPIOA->BSRR = DE_Pin; + uint8_t msg[datasize]; + for(int i = 0; i> 24; + msg[1] = DATA_READ >> 16; + msg[2] = DATA_READ >> 8; + msg[3] = DATA_READ; + HAL_UART_Transmit(&huart2, (uint8_t *)&msg, sizeof(msg), 0xFFFF); + GPIOA->BRR = DE_Pin; + } + } + else{ + DATA_READ = *(__IO uint32_t*)address; + GPIOA->BSRR = DE_Pin; + uint8_t msg[4] = {0,0,0,0}; + msg[0] = DATA_READ >> 24; + msg[1] = DATA_READ >> 16; + msg[2] = DATA_READ >> 8; + msg[3] = DATA_READ; + HAL_UART_Transmit(&huart2, (uint8_t *)&msg, sizeof(msg), 0xFFFF); + GPIOA->BRR = DE_Pin; + } +} \ No newline at end of file diff --git a/STM_WatchDog.c b/STM_WatchDog.c new file mode 100644 index 0000000..e8ae342 --- /dev/null +++ b/STM_WatchDog.c @@ -0,0 +1,17 @@ +void wdt_enable(void) +{ + RCC -> CSR = RCC -> CSR | 0x00000001; //Enable LSI Clock + while((RCC -> CSR & 0x02)==0) + { + //add timeout code here + } + IWDG -> KR = 0x0000CCCC; //Enable IWDG + IWDG -> KR = 0x00005555; //Enable register access + IWDG -> PR = 0x010; //Set Prescaler /16 + IWDG -> RLR = 0xFFF; //Set Reload Value for 2.048 seconds + while(IWDG -> SR) //Check if flags are reset + { + //add timeout code here + } + IWDG -> KR = 0x0000AAAA; //Refresh the counter +} \ No newline at end of file diff --git a/Soft_SPI.c b/Soft_SPI.c new file mode 100644 index 0000000..d449c73 --- /dev/null +++ b/Soft_SPI.c @@ -0,0 +1,210 @@ +/* + * Soft_SPI.c + * + * Created on: Nov 26, 2019 + * Author: Adcis + * + * SCK_Pin, MOSI_Pin, MISO_Pin, CS0_Pin and CS1_Pin required to define in project + * + * Software SPI library for use with STM32 MCUs + */ +#include "main.h" +#include "Soft_SPI.h" +//#include "main.c" + +void SOFT_Power(int,int); +void SOFT_SCK(unsigned int); //rizeni SCK pinu +void SOFT_SPI(unsigned int); //rizeni MOSI pinu +void SOFT_SPI_Send(unsigned int); //odeslani zpravy po SPI +int SOFT_SPI_Receive(unsigned int); //prijem zpravy po SPI +void SOFT_CS(unsigned int); //chip select - 0 = DA prevodnik, 1 = AD prevodnik, cokoliv jineho = nezvoleno nic +void SOFT_SPI_CLK(unsigned int); //1 puls _|-|_ na SCK + + +int SOFT_Power(int x, int y){ + if (y == 0){ + return 1; + } + else if (y % 2 == 0){ + return SOFT_Power(x, y / 2) * SOFT_Power(x, y / 2); + } + else{ + return x * SOFT_Power(x, y / 2) * SOFT_Power(x, y / 2); + } +} +/** + * @brief Controls SCK + * + * @param var = set state of SCK + * + * @retval None + */ +void SOFT_SCK(unsigned int state){ + if(state == 1){ + GPIOB->BSRR = SCK_Pin; + } + else{ + GPIOB->BRR = SCK_Pin; + } +} +/** + * @brief Controls MOSI + * + * @param var = set state of MOSI + * + * @retval None + */ +void SOFT_SPI(unsigned int var){ + if(var!=0){ + GPIOB->BSRR = MOSI_Pin; + } + else{ + GPIOB->BRR = MOSI_Pin; + } +} +/** + * @brief SPI CS control + * + * @param cs = what cs pin to use + * + * @retval None + */ +void SOFT_CS(unsigned int cs){ + if(cs == 0){ + GPIOB->BSRR = CS1_Pin; + GPIOB->BRR = CS0_Pin; + } + else if(cs == 1){ + GPIOB->BSRR = CS0_Pin; + GPIOB->BRR = CS1_Pin; + } + else{ + GPIOB->BSRR = CS0_Pin; + GPIOB->BSRR = CS1_Pin; + } +} +/** + * @brief Sends SPI message + * + * @param value = what byte to send + * + * @retval None + */ +void SOFT_SPI_Send(unsigned int value){ + unsigned int valueBin[] = {0,0,0,0,0,0,0,0}; + if(value >= 128){ + valueBin[0] = 1; + value = value % 128; + } + if(value >= 64){ + valueBin[1] = 1; + value = value % 64; + } + if(value >= 32){ + valueBin[2] = 1; + value = value % 32; + } + if(value >= 16){ + valueBin[3] = 1; + value = value % 16; + } + if(value >= 8){ + valueBin[4] = 1; + value = value % 8; + } + if(value >= 4){ + valueBin[5] = 1; + value = value % 4; + } + if(value >= 2){ + valueBin[6] = 1; + } + valueBin[7] = value % 2; + + SOFT_SCK(0); + SOFT_SPI(valueBin[0]); + SOFT_SCK(0); + SOFT_SCK(1); + SOFT_SPI(valueBin[1]); + SOFT_SCK(0); + SOFT_SCK(1); + SOFT_SPI(valueBin[2]); + SOFT_SCK(0); + SOFT_SCK(1); + SOFT_SPI(valueBin[3]); + SOFT_SCK(0); + SOFT_SCK(1); + SOFT_SPI(valueBin[4]); + SOFT_SCK(0); + SOFT_SCK(1); + SOFT_SPI(valueBin[5]); + SOFT_SCK(0); + SOFT_SCK(1); + SOFT_SPI(valueBin[6]); + SOFT_SCK(0); + SOFT_SCK(1); + SOFT_SPI(valueBin[7]); + SOFT_SCK(0); + SOFT_SCK(1); + GPIOB->BRR = MOSI_Pin; + SOFT_SCK(0); +} +/** + * @brief Recieves SPI message + * + * @param bits = how long will received mesage be + * + * @retval uint16_t + */ +int SOFT_SPI_Receive(unsigned int bits){ + uint8_t arr_bts[bits]; + uint8_t sumarr[bits]; + uint16_t sum; + for(int i=0; iCCR1 controls length of CH1 pulse after center and length of CH2 pulse before center. + * TIMx->CCR2 controls length of CH1 pulse before center and length of CH2 pulse after center. + * TIMx->CCR3,4 controls length of CH3,4 pulse after center +*/ + +/* PWM dynamic duty cycle: + * TIMx->CCMRxOutput ->-> OCxPE = 1 // setup of shaddow register + * TIMx->CCRx = x // set pulse length + * shaddow register is important for stability of program, because the new value will be written, when new + * cycle is begun. +*/ + +//enable period elapsed callback +TIM3->DIER |= 1 << 0; + +//callbacks +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ + if(htim -> Instance == TIM3){ + } +} + +void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){ + if(htim -> Instance == TIM3){ + } +} diff --git a/Trace_debug.md b/Trace_debug.md new file mode 100644 index 0000000..13e6943 --- /dev/null +++ b/Trace_debug.md @@ -0,0 +1,43 @@ +# All you need to know +## Debugger modification: +connect PA10 (pin 31) to one of the debugger pins for example to one of the 5V pins. +## Software +### printf adaptation: +For printf function to work we need _write method.
+```c +int _write(int file, char *ptr, int len){ + int DataIdx; + for(DataIdx=0; DataIdx +Make sure you know core frequency.
+
+Initial code:
+```c +#include stdio.h + +#define ITM_Port32(n) (*((volatile unsigned long *)(0xE0000000+4*n))) +``` +Example code before while loop:
+```c +SystemClock_Config(); + +ITM_Port32(31) = 1; + +MX_GPIO_Init(); + +printf("gpio init done \r\n"); +ITM_Port32(31) = 2; +``` +In debug configuration enable SWV and make sure Core clock matches clock of processor
+For view the trace data go to Window>Show view>SWV
+
+M0 and M0+ cortex MCUs are not supported
+Make sure, that you have selected output port in "Configure trace" + +For more info: https://www.youtube.com/watch?list=PLXnwAHPMBciEfY6C6rnz6rUehFxCQMwzY&v=4wT9NhlcWP4&feature=emb_title \ No newline at end of file diff --git a/UART.c b/UART.c new file mode 100644 index 0000000..e04c9ea --- /dev/null +++ b/UART.c @@ -0,0 +1,115 @@ +//##Interrupt receive per character +uint8_t WholeRxBuffer[256]; +uint8_t RX[1]; +uint8_t ptr = 0; + +//setup +HAL_UART_Receive_IT(&huart3, RX, 1); + +//callback +void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){ + WholeRxBuffer[ptr] = RX[0]; + ptr++; + HAL_UART_Receive_IT(&huart3, RX, 1); +} + +//##DMA receive + +//je potreba povolit DMA na uart RX +#include "Alink.h" + +uint8_t readBuffer[RX_BUFFER]; +uint8_t RX[RX_BUFFER]; + +//inicializace uartu - interface,buffer,velikost zpravy +HAL_UART_Receive_DMA(&huart1,readBuffer,sizeof(readBuffer)); + +//vysilani zpravy +HAL_UART_Transmit(&huart1, (uint8_t *)&"\nThe cake is a lie", 18, 0xFFFF); + +//presouvani dat z prijimaciho bufferu do cteciho bufferu (prijimaci buffer se ctenim maze) +for(int i = 0; i 6){ + uint8_t data[msgLen-6]; + for(int i = 0; i 4294967296/2){ + n = 4294967296 - n; + operator = '-'; + } + char tmp[11]; + int i = sizeof(tmp); + for(int j = 0; j +#include <_syslist.h> +#include +#include +#include +#include +#include +#include <../Inc/retarget.h> +#include +#include + +#if !defined(OS_USE_SEMIHOSTING) + +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +UART_HandleTypeDef *gHuart; + +void RetargetInit(UART_HandleTypeDef *huart) { + gHuart = huart; + + /* Disable I/O buffering for STDOUT stream, so that + * chars are sent out as soon as they are printed. */ + setvbuf(stdout, NULL, _IONBF, 0); +} + +int _isatty(int fd) { + if (fd >= STDIN_FILENO && fd <= STDERR_FILENO) + return 1; + + errno = EBADF; + return 0; +} + +int _write(int fd, char* ptr, int len) { + HAL_StatusTypeDef hstatus; + + if (fd == STDOUT_FILENO || fd == STDERR_FILENO) { + hstatus = HAL_UART_Transmit(gHuart, (uint8_t *) ptr, len, HAL_MAX_DELAY); + if (hstatus == HAL_OK) + return len; + else + return EIO; + } + errno = EBADF; + return -1; +} + +int _close(int fd) { + if (fd >= STDIN_FILENO && fd <= STDERR_FILENO) + return 0; + + errno = EBADF; + return -1; +} + +int _lseek(int fd, int ptr, int dir) { + (void) fd; + (void) ptr; + (void) dir; + + errno = EBADF; + return -1; +} + +int _read(int fd, char* ptr, int len) { + HAL_StatusTypeDef hstatus; + + if (fd == STDIN_FILENO) { + hstatus = HAL_UART_Receive(gHuart, (uint8_t *) ptr, 1, HAL_MAX_DELAY); + if (hstatus == HAL_OK) + return 1; + else + return EIO; + } + errno = EBADF; + return -1; +} + +int _fstat(int fd, struct stat* st) { + if (fd >= STDIN_FILENO && fd <= STDERR_FILENO) { + st->st_mode = S_IFCHR; + return 0; + } + + errno = EBADF; + return 0; +} + +#endif //#if !defined(OS_USE_SEMIHOSTING) \ No newline at end of file diff --git a/printf/retarget.h b/printf/retarget.h new file mode 100644 index 0000000..66a9537 --- /dev/null +++ b/printf/retarget.h @@ -0,0 +1,18 @@ +// All credit to Carmine Noviello for this code +// https://github.com/cnoviello/mastering-stm32/blob/master/nucleo-f030R8/system/include/retarget/retarget.h + +#ifndef _RETARGET_H__ +#define _RETARGET_H__ + +#include "stm32l4xx_hal.h" +#include + +void RetargetInit(UART_HandleTypeDef *huart); +int _isatty(int fd); +int _write(int fd, char* ptr, int len); +int _close(int fd); +int _lseek(int fd, int ptr, int dir); +int _read(int fd, char* ptr, int len); +int _fstat(int fd, struct stat* st); + +#endif //#ifndef _RETARGET_H__ \ No newline at end of file diff --git a/printf/usage.md b/printf/usage.md new file mode 100644 index 0000000..0e2eec1 --- /dev/null +++ b/printf/usage.md @@ -0,0 +1,17 @@ +Right-click on the syscalls.c file and select Properties. Under C/C++ Build > Settings, check Exclude resource from build. + +in main.c:
+```c +#include +#include "retarget.h" +char buf[100]; +RetargetInit(&huart1); +``` + +Example:
+```c +printf("\r\nYour name: "); +scanf("%s", buf); +printf("\r\nHello, %s!\r\n", buf); + +``` \ No newline at end of file