STM32 HAL C QuadSPI Display read and write - c

I am using QSPI not to connect memory, but a FTDI display.
I used STM32CubeMX and Atollic TrueStudio. I included FreeRTOS, but I'm not using that, yet.
Using QuadSPI, I have trouble to read and write 1, 2 or 4 bytes, where I transmit a 3 byte memory address.
If I try to read an address like this, it times out at HAL_QSPI_Receive, and no signals are generated on the bus, if I configure
s_command.AddressMode = QSPI_ADDRESS_1_LINE;
If I configure
s_command.AddressMode = QSPI_ADDRESS_NONE;
Signals are generated to read a byte, but the address is not send of course.
To send the address and receive bytes afterwards, I send the address in the Alternate bytes. But now the number of bytes can 1 or 2, but not 4, because I will get a time-out again.
My code pieces
uint8_t pData[4];
uint32_t address = REG_ID;
QspiReadData(address, 1, pData);
uint32_t v = 0x12345678;
pData[0] = v >> 24;
pData[1] = (v >> 16) & 0xff;
pData[2] = (v >> 8) & 0xff;
pData[3] = v & 0xff;
QspiWriteData(addr, 4, pData);
uint8_t QspiReadData(uint32_t address, uint32_t size, uint8_t* pData)
{
QSPI_CommandTypeDef s_command;
QSPI_AutoPollingTypeDef s_config;
/* Initialize the read command */
s_command.InstructionMode = QSPI_INSTRUCTION_NONE;
s_command.Instruction = 0;
s_command.AddressMode = QSPI_ADDRESS_1_LINE;
s_command.AddressSize = QSPI_ADDRESS_32_BITS;
s_command.Address = address;
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
s_command.AlternateBytes = 0;
s_command.AlternateBytesSize = 0;
s_command.DataMode = QSPI_DATA_1_LINE; // QSPI_DATA_4_LINES
s_command.DummyCycles = 0;
s_command.NbData = size;
s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
/* Configure the command */
printf("HAL_QSPI_Command\n");
if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
printf("HAL_ERROR\n");
return HAL_ERROR;
}
/* Reception of the data */
printf("HAL_QSPI_Receive\n");
if (HAL_QSPI_Receive(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
printf("HAL_ERROR\n"); // Timeout after 5000mS
return HAL_ERROR;
}
return HAL_OK;
}
/* QUADSPI init function */
void MX_QUADSPI_Init(void)
{
hqspi.Instance = QUADSPI;
hqspi.Init.ClockPrescaler = 254; /* 4 QSPI Freq= 108 MHz / (1+4) = 21.6 MHz */
hqspi.Init.FifoThreshold = 1;
hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
hqspi.Init.FlashSize = 0;
hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_8_CYCLE;
hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0; // QSPI_CLOCK_MODE_0 Rising edge CPOL=0, QSPI_CLOCK_MODE_3 Falling edge CPOL=1
hqspi.Init.FlashID = QSPI_FLASH_ID_1;
hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
if (HAL_QSPI_Init(&hqspi) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
uint8_t QspiWriteData(uint32_t address, uint32_t size, uint8_t* pData)
{
QSPI_CommandTypeDef s_command;
printf("Ft813QspiReadData8(%ld, %d, pData)\n", address, size);
/* Initialize the read command */
s_command.InstructionMode = QSPI_INSTRUCTION_NONE;
s_command.Instruction = 0;
s_command.AddressMode = QSPI_ADDRESS_NONE;
s_command.AddressSize = QSPI_ADDRESS_24_BITS;
s_command.Address = 0;
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_1_LINE;
s_command.AlternateBytes = address;
s_command.AlternateBytesSize = QSPI_ALTERNATE_BYTES_24_BITS;
s_command.DataMode = QSPI_DATA_1_LINE;
s_command.DummyCycles = 0;
s_command.NbData = size;
s_command.DdrMode = QSPI_DDR_MODE_DISABLE;
s_command.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
s_command.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
/* Configure the command */
printf("HAL_QSPI_Command\n");
if (HAL_QSPI_Command(&hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
printf("HAL_ERROR\n");
return HAL_ERROR;
}
/* Reception of the data */
printf("HAL_QSPI_Transmit\n");
if (HAL_QSPI_Transmit(&hqspi, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
printf("HAL_ERROR\n");
return HAL_ERROR;
}
return HAL_OK;
}
What can be the problem?
The GPIO pins were configured like this, in case it helps sombody else:
void HAL_QSPI_MspInit(QSPI_HandleTypeDef* qspiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(qspiHandle->Instance==QUADSPI)
{
/* USER CODE BEGIN QUADSPI_MspInit 0 */
/* USER CODE END QUADSPI_MspInit 0 */
/* QUADSPI clock enable */
__HAL_RCC_QSPI_CLK_ENABLE();
/**QUADSPI GPIO Configuration
PF6 ------> QUADSPI_BK1_IO3
PF7 ------> QUADSPI_BK1_IO2
PF8 ------> QUADSPI_BK1_IO0
PF9 ------> QUADSPI_BK1_IO1
PF10 ------> QUADSPI_CLK
PB10 ------> QUADSPI_BK1_NCS
*/
GPIO_InitStruct.Pin = QUADSPI_BK1_IO3_Pin|QUADSPI_BK1_IO2_Pin|QUADSPI_CLK_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
GPIO_InitStruct.Pin = QUADSPI_BK1_IO0_Pin|QUADSPI_BK1_IO1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
GPIO_InitStruct.Pin = QUADSPI_BK1_NCS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
HAL_GPIO_Init(QUADSPI_BK1_NCS_GPIO_Port, &GPIO_InitStruct);
/* QUADSPI DMA Init */
/* QUADSPI Init */
hdma_quadspi.Instance = DMA2_Stream2;
hdma_quadspi.Init.Channel = DMA_CHANNEL_11;
hdma_quadspi.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_quadspi.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_quadspi.Init.MemInc = DMA_MINC_ENABLE;
hdma_quadspi.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_quadspi.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_quadspi.Init.Mode = DMA_NORMAL;
hdma_quadspi.Init.Priority = DMA_PRIORITY_LOW;
hdma_quadspi.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_quadspi) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
__HAL_LINKDMA(qspiHandle,hdma,hdma_quadspi);
/* QUADSPI interrupt Init */
HAL_NVIC_SetPriority(QUADSPI_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(QUADSPI_IRQn);
/* USER CODE BEGIN QUADSPI_MspInit 1 */
/* USER CODE END QUADSPI_MspInit 1 */
}
}

hqspi.Init.FlashSize = 0; is wrong. QuadSPI module needs to learn the memory of device which will write/read. Change it with 31. It will run.

Related

Receiving random data bytes during STM32 CAN communication Rx

I'm using STM32F103RBT6 Nucleo board with CAN communication for my project. I use Microchip CAN Bus Analyzer(acts as a node) to transmit CAN data.
Project Setup:
CAN message flow from: CAN Bus Analyzer --> CAN Transceiver --> STM board.
I need to receive messages only from 0x581, 0x582, 0x583, 0x584, 0x4A1, 0x4A2, 0X4A3, 0X4A4 IDs. In order to achieve this I have applied filters for the same.
Problem:
In Keil's debugger mode, I'm able to see the CAN messages which are transmitted, getting received in 'RxData' properly. However when I try to send data of 4 bytes length, RxData data bytes from 1 to 4 gets filled with the exact same message that I transmit, but data bytes 5 to 8 also gets filled randomly (In ideal case, bytes 5 to 8 should all be zero). This problem happens only when I send data of byte length 4. I tried sending data bytes of varying length (other than 4), it worked just fine. The problem lies only whenever I try to send data byte of length 4.
I have attached my entire program code below. And attached screenshots of the issue. Please find below.
#include "main.h"
CAN_HandleTypeDef hcan;
CAN_TxHeaderTypeDef TxHeader;
CAN_RxHeaderTypeDef RxHeader;
CAN_FilterTypeDef sFilterConfig;
uint8_t RxData[8];
uint8_t TxData[8];
uint32_t TxMailbox;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_CAN_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_CAN_Init();
while (1)
{
// Empty while.
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}
static void MX_CAN_Init(void)
{
hcan.Instance = CAN1;
hcan.Init.Prescaler = 2;
hcan.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan.Init.TimeSeg1 = CAN_BS1_10TQ;
hcan.Init.TimeSeg2 = CAN_BS2_1TQ;
hcan.Init.TimeTriggeredMode = DISABLE;
hcan.Init.AutoBusOff = DISABLE;
hcan.Init.AutoWakeUp = DISABLE;
hcan.Init.AutoRetransmission = DISABLE;
hcan.Init.ReceiveFifoLocked = DISABLE;
hcan.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK)
{
Error_Handler();
}
uint16_t StdIdArray1 [4] = {0x581, 0x582, 0x583, 0x584}; // 0x58x ID Series
uint16_t StdIdArray2 [4] = {0x4A1, 0x4A2, 0x4A3, 0x4A4}; // 0x4Ax ID Series
uint16_t mask, tmp, i, num;
sFilterConfig.FilterBank = 5;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; // Mask Mode
sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT; // 16 Bit
sFilterConfig.FilterIdLow = StdIdArray1[0] << 5; // Filter Id Low
mask = 0x5ff;
num = sizeof (StdIdArray1)/sizeof (StdIdArray1[0]); // Mask code
for (i = 0; i <num; i ++)
{
tmp = StdIdArray1[i]^(~StdIdArray1 [0]);
mask &= tmp;
}
sFilterConfig.FilterMaskIdLow = (mask << 5) | 0x10; // Filter Mask Id Low
sFilterConfig.FilterIdHigh = StdIdArray2[0] << 5; // Filter Id High
mask = 0x4ff;
num = sizeof (StdIdArray2)/sizeof (StdIdArray2[0]); // Mask code
for (i = 0; i <num; i ++)
{
tmp = StdIdArray2[i]^(~ StdIdArray2[0]);
mask &= tmp;
}
sFilterConfig.FilterMaskIdHigh = (mask << 5) | 0x10; // Filter Mask Id High
sFilterConfig.FilterFIFOAssignment = 0; // FIFO 0
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.SlaveStartFilterBank = 14;
if (HAL_CAN_ConfigFilter(&hcan,&sFilterConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_CAN_Start(&hcan) != HAL_OK)
{
Error_Handler();
}
if (HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
}
/* Receive Callback. Get messages from the CAN bus analyzer */
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
{
Error_Handler();
}
if (HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
{
Error_Handler();
}
}
void Error_Handler(void)
{
}
void assert_failed(uint8_t *file, uint32_t line)
{
}
Screenshots:
Case 1:
ID= 581; DLC= 8;
enter image description here
Case 2:
ID = 581; DLC=6;
enter image description here
Case 3:
ID= 581; DLC=2;
enter image description here
Case 4: (Issue)
ID = 581; DLC=4;
enter image description here
Case 5: (Issue)
ID= 4A1; DLC=4;
enter image description here
This issue is only with data byte of length 4. It could be of great help if someone can help me resolve this!

STM32: simple SPI transfer

I am working with a STM32F3DISCOVERY board and I'm trying to dive a bit deeper into the abstractions of the HAL. I made a simple version of a function that transmits data over SPI, sadly it does not work (at least the DAC I'm sending it to does not change state) and I'm not sure what I am missing there. Maybe there's also something in the initialization code that doesn't work with my simple version. I'd be happy for any guidance or references I could check. Thank you!
#include <stm32f3xx_hal.h>
#define PINS_SPI GPIO_PIN_5 | GPIO_PIN_7
#define GPIO_PORT GPIOA
/* This is the simplest function I could come up with to do the transfer but I'm clearly missing something here */
uint8_t SPI_SendReceive(SPI_HandleTypeDef *hspi, uint8_t data) {
/* Loop while DR register in not empty */
while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET) {
}
/* Send data through the SPI1 peripheral */
hspi->Instance->DR = data;
/* Wait to receive data */
while ((hspi->Instance->SR & SPI_FLAG_RXNE) == RESET) {
}
return hspi->Instance->DR;
}
int main() {
HAL_Init();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_SPI1_CLK_ENABLE();
static SPI_HandleTypeDef spi = {.Instance = SPI1};
spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
spi.Init.Direction = SPI_DIRECTION_2LINES;
spi.Init.CLKPhase = SPI_PHASE_1EDGE;
spi.Init.CLKPolarity = SPI_POLARITY_LOW;
spi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
spi.Init.DataSize = SPI_DATASIZE_8BIT;
spi.Init.FirstBit = SPI_FIRSTBIT_MSB;
spi.Init.NSS = SPI_NSS_HARD_OUTPUT;
spi.Init.TIMode = SPI_TIMODE_DISABLE;
spi.Init.Mode = SPI_MODE_MASTER;
HAL_SPI_Init(&spi);
__HAL_SPI_ENABLE(&spi);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = PINS_SPI;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* TI 8564 DAC Settings */
uint8_t cmd1 = 0b00010000;
/* DAC output value (16-bit) */
uint16_t cmd23 = 0;
uint8_t cmd2 = cmd23 >> 8;
uint8_t cmd3 = cmd23 & 0xff;
uint8_t command[3] = {cmd1, cmd2, cmd3};
while (true) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
/* This does not work :( */
SPI_SendReceive(&spi, command[0]);
SPI_SendReceive(&spi, command[1]);
SPI_SendReceive(&spi, command[2]);
/* This works! When commenting in the lines above and commenting this out */
/* HAL_SPI_Transmit(&spi, command, 3, HAL_MAX_DELAY); */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
HAL_Delay(1000);
}
}
Check the contents of HAL_SPI_Init. Most likely this function calls another function which is supposed to do the low-level initialization, and you're responsible to provide this function yourself. To make it more complex, this alleged second function already has a "dummy" weak alias defined, so the toolchain doesn't return any error but just builds a code unable to do anything.

STM32L0 LoRaWAN Discovery Board: Trigger RTC Alarm Every 250 Milliseconds

Ultimately, what I would like to do is to trigger an alarm to wake up the STM32L0 every 250 milliseconds, do some functionality, and then go back into sleep mode. What I am attempting to do now with this code as a proof of concept for the RTC Alarm. It is to trigger the alarm every second. This is confirmed by the wake_up_flag=1 in the alarm callback. I am using a custom printf function and a function to show RTC time and the value of the wake up flag, which I excluded to focus on the code related to my problem.
The problem is the RTC seems to be working and keeping track of time, but the alarm callback never triggers and I do not have any idea why. I produced most of this code with STM32CubeIDE and to the best of my knowledge, enabled everything I needed to. I am new to STM32CubeIDE and any help would be greatly appreciated. Thank you in advanced.
Main Loop:
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI1_Init();
MX_USART2_UART_Init();
MX_RTC_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
RTC_TimeShow();
my_printf("WAKE UP FLAG %d\n" ,wake_up_flag);
if(wake_up_flag == 1){
wake_up_flag = 0;
my_printf("WOKE UP");
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(1000);
}
/* USER CODE END 3 */
}
Alarm Callback:
void HAL_RTC_AlarmEventCallback(RTC_HandleTypeDef *hrtc){
wake_up_flag = 1;
}
RTC Initialization:
static void MX_RTC_Init(void)
{
/* Enable the RTC Alarm Interrupt */
/* USER CODE BEGIN RTC_Init 0 */
/* USER CODE END RTC_Init 0 */
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
RTC_AlarmTypeDef sAlarm = {0};
/* USER CODE BEGIN RTC_Init 1 */
/* USER CODE END RTC_Init 1 */
/** Initialize RTC Only
*/
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN Check_RTC_BKUP */
/* USER CODE END Check_RTC_BKUP */
/** Initialize RTC and set the Time and Date
*/
sTime.Hours = 0x0;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
sDate.WeekDay = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_JANUARY;
sDate.Date = 0x1;
sDate.Year = 0x0;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
/** Enable the Alarm A
*/
sAlarm.AlarmTime.Hours = 0x0;
sAlarm.AlarmTime.Minutes = 0x0;
sAlarm.AlarmTime.Seconds = 0x0;
sAlarm.AlarmTime.SubSeconds = 0x0;
sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
sAlarm.AlarmMask = RTC_ALARMMASK_ALL;
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE;
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
sAlarm.AlarmDateWeekDay = 0x1;
sAlarm.Alarm = RTC_ALARM_A;
if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
}
GPIO Configuration:
/**
* #brief GPIO Initialization Function
* #param None
* #retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, PA15_RESERVED_Pin|PA12_RESERVED_Pin|PA1_RESERVED_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, PC1_RESERVED_Pin|PC0_RESERVED_Pin|PC2_RESERVED_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : PA15_RESERVED_Pin PA12_RESERVED_Pin PA1_RESERVED_Pin */
GPIO_InitStruct.Pin = PA15_RESERVED_Pin|PA12_RESERVED_Pin|PA1_RESERVED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PB4_RESERVED_Pin PB1_RESERVED_Pin PB0_RESERVED_Pin */
GPIO_InitStruct.Pin = PB4_RESERVED_Pin|PB1_RESERVED_Pin|PB0_RESERVED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pin : PC13_RESERVED_Pin */
GPIO_InitStruct.Pin = PC13_RESERVED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(PC13_RESERVED_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : PC1_RESERVED_Pin PC0_RESERVED_Pin PC2_RESERVED_Pin */
GPIO_InitStruct.Pin = PC1_RESERVED_Pin|PC0_RESERVED_Pin|PC2_RESERVED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI0_1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
HAL_NVIC_SetPriority(EXTI4_15_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
}
I ended up needing to modify the RTC.h and RTC.c file with another RTC type like as follows:
In RTC.h, I modified and added another Alarm match for 250 milliseconds as below.
enum AlarmMatch: uint8_t {
MATCH_250MS = 7, //Every 256 milliseconds
MATCH_ANY = 0, // Every Second
MATCH_SS = 1, // Every Minute
MATCH_MMSS = 2, // Every Hour
MATCH_HHMMSS = 3, // Every Day
MATCH_DHHMMSS = 4, // Every Month
MATCH_MMDDHHMMSS = 5, // Every Year
MATCH_YYMMDDHHMMSS = 6, // Once, on a specific date and a specific time
};
In RTC.c , in the void RTCClass::AdvanceAlarm() function, I added the following to the alarm switch. The second parameter was based on seconds. The key was that the third parameter is based on the 32.768KHz crystal (32,768 oscillations per second), so if you want 250 ms, that is 1/4 of 32,768 which is 8192.
switch (_alarm_match) {
case MATCH_250MS:
_alarm_calendar.year = calendar.year;
_alarm_calendar.month = calendar.month;
_alarm_calendar.day = calendar.day;
_alarm_calendar.hours = calendar.hours;
_alarm_calendar.minutes = calendar.minutes;
_alarm_calendar.seconds = calendar.seconds;
stm32l0_rtc_calendar_offset(&_alarm_calendar, 0, 8192, &_alarm_calendar);
break;

HAL_UART_Transmit sends wrong data

When ch = 0x80, on PC I receive 0x00,
When ch = 0x40, on PC I receive 0x80,
When ch = 0x20, on PC I receive 0x60,
When ch = 0x10, on PC I receive 0x10,
When ch = 0x08, on PC I receive 0x08,
When ch = 0x04, on PC I receive 0x04,
When ch = 0x02, on PC I receive 0x02,
When ch = 0x01, on PC I receive 0x01,
Can't figure what is going on here... I am attaching USART Initialization, Transmit Function and Main. I should be software issue, already tested the hardware and it's ok. MCU = STM32L011
void InitUSART(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
USARTx_CLK_ENABLE();
UartHandle.Instance = USARTx;
UartHandle.Init.BaudRate = 9600;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle.Init.Mode = UART_MODE_TX_RX;
//UartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_ENABLE;
HAL_UART_Init(&UartHandle);
/* Transmit Configuration */
USARTx_TX_GPIO_CLK_ENABLE();
GPIO_InitStruct.Pin = USARTx_TX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = USARTx_TX_AF;
HAL_GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStruct);
/* Receive Configuration */
USARTx_RX_GPIO_CLK_ENABLE();
GPIO_InitStruct.Pin = USARTx_RX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = USARTx_TX_AF;
HAL_GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStruct);
HAL_NVIC_SetPriority(USARTx_IRQn, 0, 1);
HAL_NVIC_EnableIRQ(USARTx_IRQn);
}
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
uint16_t* tmp;
uint32_t tickstart = 0;
/* Check that a Tx process is not already ongoing */
if(huart->gState == HAL_UART_STATE_READY)
{
if((pData == NULL ) || (Size == 0U))
{
return HAL_ERROR;
}
/* In case of 9bits/No Parity transfer, pData buffer provided as input paramter
should be aligned on a u16 frontier, as data to be filled into TDR will be
handled through a u16 cast. */
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
{
if((((uint32_t)pData)&1) != 0)
{
return HAL_ERROR;
}
}
/* Process Locked */
__HAL_LOCK(huart);
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_BUSY_TX;
/* Init tickstart for timeout managment*/
tickstart = HAL_GetTick();
huart->TxXferSize = Size;
huart->TxXferCount = Size;
while(huart->TxXferCount > 0U)
{
huart->TxXferCount--;
if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
{
tmp = (uint16_t*) pData;
huart->Instance->TDR = (*tmp & (uint16_t)0x01FFU);
pData += 2U;
}
else
{
huart->Instance->TDR = (*pData++ & (uint8_t)0xFFU);
}
}
if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
{
return HAL_TIMEOUT;
}
/* At end of Tx process, restore huart->gState to Ready */
huart->gState = HAL_UART_STATE_READY;
/* Process Unlocked */
__HAL_UNLOCK(huart);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
int main(void)
{
/* STM32L0xx HAL library initialization:
- Configure the Flash prefetch, Flash preread and Buffer caches
- Systick timer is configured by default as source of time base, but user
can eventually implement his proper time base source (a general purpose
timer for example or other time source), keeping in mind that Time base
duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
handled in milliseconds basis.
- Low Level Initialization
*/
HAL_Init();
/* Configure the system clock to 32 MHz */
SystemClock_Config();
InitUSART();
//Transmit(txBuffer, 2);
extern UART_HandleTypeDef UartHandle;
uint16_t ch = 0x80;
TransmitEnable();
while(1){
HAL_UART_Transmit(&UartHandle, &ch, 1, 0xFF);
HAL_Delay(5);
}
}
Looks like it was a clock issue after all. I was using internal 16 MHz oscillator (HSI) multiplied up to 32 MHz with PLL. Single baud width on 9600 baudrate was 110us. Now I switched to 4 MHz (internal MSI) and I am getting 104us per baud. Communication is flawless now.
RCC_ClkInitTypeDef RCC_ClkInitStruct ={0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0)!= HAL_OK)
{
while(1);
}
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
__HAL_RCC_PWR_CLK_DISABLE();
Acording your sent source file, you programmed the usart as "8 bits", but this STM HAL routine compute data_bits+parity_bit=8bits(your selection). For standard text transmission, for this STM HAL should be: 9 bits (8_data_bits+one_parity_bit).

STM32L4 - SPI2 clocking issue

I am currently working on the STM32L476RG Nucleo board and I am trying to communicate with the SPI2 bus.
It seems that I am sending data with the MOSI pin but I don't have anything on the SCK pin.
Here are my initialisation code and sending data code:
In the main.c:
/Function that initializes the SPI/
void MX_SPI2_Init(void)
{
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLED;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
hspi2.Init.CRCPolynomial = 7;
hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLED;
HAL_SPI_Init(&hspi2);
}
/Function that sends data via SPI to the slave/
void ADAS1000_SetRegisterValue(unsigned char regAddress,
unsigned long regVal)
{
unsigned char writeCmd[4] = {0, 0, 0, 0};
writeCmd[0] = 0x80 + regAddress; // Write bit and register address.
writeCmd[1] = (unsigned char)((regVal & 0xFF0000) >> 16);
writeCmd[2] = (unsigned char)((regVal & 0x00FF00) >> 8);
writeCmd[3] = (unsigned char)((regVal & 0x0000FF) >> 0);
HAL_SPI_Transmit(&hspi2, &(writeCmd[0]), (uint16_t) sizeof(writeCmd[0]), 50);
HAL_Delay(500);
HAL_SPI_Transmit(&hspi2, &(writeCmd[1]), (uint16_t) sizeof(writeCmd[1]), 50);
HAL_Delay(500);
HAL_SPI_Transmit(&hspi2, &(writeCmd[2]), (uint16_t) sizeof(writeCmd[2]), 50);
HAL_Delay(500);
HAL_SPI_Transmit(&hspi2, &(writeCmd[3]), (uint16_t) sizeof(writeCmd[3]), 50);
HAL_Delay(500);
}
In the hal_msp.c :
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hspi->Instance==SPI2)
{
/* Peripheral clock enable */
__SPI2_CLK_ENABLE();
/**SPI2 GPIO Configuration
PC2 ------> SPI2_MISO
PC3 ------> SPI2_MOSI
PB10 ------> SPI2_SCK
PB12 ------> SPI2_NSS
*/
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
If you have any ideas or advice, thanks for helping!
EDIT
void MX_GPIO_Init(void)
{
/* GPIO Ports Clock Enable */
__GPIOC_CLK_ENABLE();
__GPIOA_CLK_ENABLE();
__GPIOB_CLK_ENABLE();
}
This might be the problem:
// [...]
hspi2.Init.NSS = SPI_NSS_SOFT;
// [...]
Without checking the definition of your HAL macros, I believe that this configures the SPI not to drive NSS - but to have this done by software. This means that you are responsible to assert the NSS pin manually before putting data into the SPI peripheral.
This in turn may cause the SPI slave side not to respond, which may appear like the SCK signals weren't reaching the slave at all.

Resources