I am trying to communicate 2 STM32 with I2C.My configuration is as followed:
7-bit addressing mode (no dual address, only OAR1)
100khz speed
ACK enabled (on slave)
ACK disabled (on master, since only 1 byte is transferred between master/slave at any time)
on both master/slave, using GPIOB (PB6) as SCL as AF and GPIOB (PB7) as SDA as AF.Where is the problem?
Master code:
#include "stm32f10x.h" // Device header #include "delay.h"
void pinConfig(void);
void i2c_Master_Config(void);
void sendData(uint8_t data);
int main() {
delay_init();
pinConfig();
i2c_Master_Config();
while(1)
{
uint8_t butonState=GPIOA->IDR & 0x00001000;
sendData(0x68,butonState);
delay_ms(10);
}
}
void pinConfig() {
RCC->APB1ENR |=1<<21;//Enable I2C 1 clock
RCC->APB2ENR |=1<<2;//Enable GPIOA clock
RCC->APB2ENR |=1<<3;//Enable GPIOB clock
RCC->APB2ENR |=1<<0;//Enable AFIO clock
GPIOA->CRL |= 0x00008000; //PA3 button pull-down
GPIOB->CRL = 0xFF000000; //SCL and SDA AF Open Drain SCL => PB6 SDA =>PB7
}
void i2c_Master_Config() {
I2C1->CR2 |=1<<5; //36 Mhz peripheral clock.
I2C1->CR2 |=1<<2; //36 Mhz peripheral clock.
I2C1->CCR =0x28;//100 khz clock
I2C1->TRISE =9;//1/8MHZ= 125 ns => 1000ns/125ns =8 => 8+1 =9
I2C1->CR1 |=(1<<0);//Peripheral enable..
}
void sendData(uint8_t data) {
volatile int temp;
while(I2C1->SR2 &(1<<1));//BUSY bit.
I2C1->CR1 |=1<<8;//START bit.
while(!(I2C1->SR1 & (1<<0))); //wait until start flag is set
I2C1->DR = slaveAdres<<1;//7 bit adress.
while(!(I2C1->SR1 &(1<<1)));//wait until addr flag is set
gecici=I2C1->SR2;//clear addr flag.
I2C1->DR = data;
while (!(I2C1->SR1 & (1<<7))){} //wait until txe is set
while (!(I2C1->SR1 & (1<<2)));//BTF(Byte transfer finished)=1 .
I2C1->CR1 |= 1<<9;//STOP bit.
I2C1->CR1 &=~(1<<0);//Peripheral disable.
}
Slave code:
#include "stm32f10x.h" // Device header
void pinConfig(void);
void i2c_Slave_Config(void);
uint8_t readData(void);
uint8_t data;
int main()
{
pinConfig();
i2c_Slave_Config();
while(1)
{
data=readData();
if(data==0)
GPIOB->BSRR |=1<<3;
else if(data==1)
GPIOB->BRR |=1<<3;
}
}
void pinConfig()
{
RCC->APB1ENR |=1<<21;//I2C 1 Clock Aktif.
RCC->APB2ENR |=1<<2;//Enable GPIOA clock
RCC->APB2ENR |=1<<3;//Enable GPIOB clock
RCC->APB2ENR |=1<<0;//Enable AFIO clock
GPIOA->CRL |= 0x00002000; //PA3 led.
GPIOB->CRL = 0xFF000000; //SCL and SDA AF Open Drain SCL => PB6 SDA =>PB7
GPIOA->BSRR |=1<<3;//Turn off the led.
}
void i2c_Slave_Config() {
RCC->APB1ENR |=1<<21;//I2C 1 Clock Enable.
I2C1->CR2 |=1<<5; //36 Mhz peripheral clock.
I2C1->CR2 |=1<<2; //36 Mhz peripheral clock.
I2C1->CCR =0x28;//100 khz clock
I2C1->OAR1 &=~(1<<15);//7-bit slave adress.
I2C1 ->CR1 |= 1<<10;//ACK enable.
//0x68 Slave Adress Configured.
I2C1 ->OAR1 &=~(1<<1);
I2C1 ->OAR1 &=~(1<<2);
I2C1 ->OAR1 &=~(1<<3);
I2C1 ->OAR1 &=~(1<<5);
I2C1 ->OAR1 |=(1<<4);
I2C1 ->OAR1 |=(1<<6);
I2C1 ->OAR1 |=(1<<7);
//0x68 Slave Adress Configured.
}
uint8_t readData()
{
volatile int temp;
uint8_t data;
I2C1->CR1 |=(1<<0);//Peripheral enable.
while(I2C1->SR2 &(1<<1));//BUSY bit.
I2C1->CR1 |=1<<8;//START bit.
while(!(I2C1->SR1 & (1<<0))); // wait until start flag is set.
while(!(I2C1->SR1 &(1<<1)));// wait until addr flag is set
temp=I2C1->SR2;//clear addr .
while (!(I2C1->SR1 & (1<<6))){} // wait until rxne is set
data=I2C1->DR;
while (!(I2C1->SR1 & (1<<4))){} // wait until STOPF is set
gecici=I2C1->SR1;
I2C1->SR1 |=1<<9;
I2C1->CR1 &=~(1<<0);//Peripheral disable.
return data;
}
Adress doesnt match. I do not see the any response on the SDA and SCL signals on the scope.I pulled both SCL and SDA to 3.3v using 4.7kohms on
each line.(STM32F103C6).
For now master I2C module enabled at main start in i2c_Master_Config(), then disabled at end of sendData() and never enabled again.
Slave I2C module enabled at the begining and disabled at the end of readData().
That is enough for broken communication. I2C peripheral module should be enabled all time (until you will understand when it should be disabled).
p.s. Sorry, I not analysed your code deeply — a lot of "magic numbers" instead of mnemonic bit names makes the analysis difficult. Perhaps, there are other mistakes.
Related
I am currently using STM32L0538 Discovery board. In my project i have to use lower level drivers to interface i2c with slave device (ST25DV) using DMA.
I ported LL example to STM32L0538 DISCO board by referring the LL example project available for NUCLEO-L073RZ in the firmware repo (STM32Cube_FW_L0_V1.12.1).
The issue with example is i am only able to transmit 4-bytes of data (slave addr. + 3bytes of 8bit data), afterwards i2c generates stop condition although the number of data to be transmitted is more than 4 bytes both in DMA and I2C register. I think the issue is with DMA, as it accepts uint32_t type source memory addr. but my data is of uint8_t type. I have tried typecasting as shown in the demo LL example but it doesn't work.
**Can anyone please tell me how can i transmit more than just 4bytes of data or where i am going wrong. ** Thanks in advance.
Here is the sample code ported from STM32L0 Firmware repo which only send 4 bytes of data:
uint8_t aLedOn[5] = {0x12,0x34,0x56,0x77,88};
__IO uint8_t ubNbDataToTransmit = sizeof(aLedOn);
uint8_t* pTransmitBuffer = (uint8_t*)aLedOn;
__IO uint8_t ubTransferComplete = 0;
#define SLAVE_OWN_ADDRESS 0xAE
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
/* Configure the system clock */
SystemClock_Config();
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
Configure_DMA();
Configure_I2C_Master();
LL_mDelay(1000);
Handle_I2C_Master();
/* USER CODE END 2 */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
}
void Configure_DMA(void)
{
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
NVIC_SetPriority(DMA1_Channel4_5_6_7_IRQn, 0);
NVIC_EnableIRQ(DMA1_Channel4_5_6_7_IRQn);
LL_DMA_ConfigTransfer(DMA1, LL_DMA_CHANNEL_4, LL_DMA_DIRECTION_MEMORY_TO_PERIPH | \
LL_DMA_PRIORITY_HIGH | \
LL_DMA_MODE_NORMAL | \
LL_DMA_PERIPH_NOINCREMENT | \
LL_DMA_MEMORY_INCREMENT | \
LL_DMA_PDATAALIGN_BYTE | \
LL_DMA_MDATAALIGN_BYTE);
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_4, ubNbDataToTransmit);
LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_4, (uint32_t)pTransmitBuffer, (uint32_t)LL_I2C_DMA_GetRegAddr(I2C2, LL_I2C_DMA_REG_DATA_TRANSMIT), LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_CHANNEL_4));
LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_4, LL_DMA_REQUEST_7);
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_4);
LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_4);
}
void Configure_I2C_Master(void)
{
LL_I2C_InitTypeDef I2C_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Enable the peripheral clock of GPIOC */
LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB);
GPIO_InitStruct.Pin = LL_GPIO_PIN_13;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LL_GPIO_PIN_14;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C2);
LL_I2C_SetTiming(I2C2, 0x00100E16);
LL_I2C_SetOwnAddress1(I2C2, 0x00, LL_I2C_OWNADDRESS1_7BIT);
LL_I2C_DisableOwnAddress1(I2C2);
LL_I2C_EnableClockStretching(I2C2);
LL_I2C_SetDigitalFilter(I2C2, 0x00);
LL_I2C_EnableAnalogFilter(I2C2);
LL_I2C_EnableGeneralCall(I2C2);
LL_I2C_SetOwnAddress2(I2C2, 0x00, LL_I2C_OWNADDRESS2_NOMASK);
LL_I2C_DisableOwnAddress2(I2C2);
LL_I2C_SetMasterAddressingMode(I2C2, LL_I2C_ADDRESSING_MODE_7BIT);
LL_I2C_SetMode(I2C2, LL_I2C_MODE_I2C);
// (4) Enable DMA transmission requests a
LL_I2C_EnableDMAReq_TX(I2C2);
LL_I2C_Enable(I2C2);
}
void Handle_I2C_Master(void)
{
ubTransferComplete = 0;
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_4);
LL_I2C_HandleTransfer(I2C2, SLAVE_OWN_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, ubNbDataToTransmit, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
/* Loop until DMA transfer complete event */
while(!ubTransferComplete)
{
}
/* Loop until STOP flag is raised */
while(!LL_I2C_IsActiveFlag_STOP(I2C2))
{
}
LL_I2C_ClearFlag_STOP(I2C2);
}
I work with a demo board B-L475E-IOT01A. On CN3 connector - pin1 - PA1-RX, pin2 - PA0-TX. So I configure for UART4.
#define UART4_PORT GPIOA
#define UART4_TX_PIN LL_GPIO_PIN_0
#define UART4_RX_PIN LL_GPIO_PIN_1
int USART_Setup(USART_TypeDef *USARTx, uint32_t baud_rate)
{
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
if (USARTx == UART4)
{
irq_num = UART4_IRQn;
/* Configure Tx Pin as : Alternate function, High Speed, Push pull, Pull up */
LL_GPIO_SetPinMode(UART4_PORT, UART4_TX_PIN, LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_8_15(UART4_PORT, UART4_TX_PIN, LL_GPIO_AF_8);
LL_GPIO_SetPinSpeed(UART4_PORT, UART4_TX_PIN, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(UART4_PORT, UART4_TX_PIN, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull(UART4_PORT, UART4_TX_PIN, LL_GPIO_PULL_UP);
/* Configure Rx Pin as : Alternate function, High Speed, Push pull, Pull up */
LL_GPIO_SetPinMode(UART4_PORT, UART4_RX_PIN, LL_GPIO_MODE_ALTERNATE);
LL_GPIO_SetAFPin_8_15(UART4_PORT, UART4_RX_PIN, LL_GPIO_AF_8);
LL_GPIO_SetPinSpeed(UART4_PORT, UART4_RX_PIN, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(UART4_PORT, UART4_RX_PIN, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull(UART4_PORT, UART4_RX_PIN, LL_GPIO_PULL_UP);
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_UART4);
LL_RCC_SetUSARTClockSource(LL_RCC_UART4_CLKSOURCE_PCLK1);
}
NVIC_SetPriority(irq_num, 0);
NVIC_EnableIRQ(irq_num);
/* TX/RX direction */
LL_USART_SetTransferDirection(USARTx, LL_USART_DIRECTION_TX_RX);
/* 8 data bit, 1 start bit, 1 stop bit, no parity */
LL_USART_ConfigCharacter(USARTx, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);
LL_USART_SetBaudRate(USARTx, SystemCoreClock, LL_USART_OVERSAMPLING_16, baud_rate);
LL_USART_Enable(USARTx);
//enable RX buffer not empty interrupt
USARTx->CR1 |= USART_CR1_RXNEIE;
/* Polling USART initialisation */
while((!(LL_USART_IsActiveFlag_TEACK(USARTx))) || (!(LL_USART_IsActiveFlag_REACK(USARTx))))
{
timeout++;
if (timeout > 1000000)
{
return USART_ERROR;
}
}
return USART_OK;
}
I go line by line in the debugger and it seems to be OK. However when I connect to a terminal with TTL-USB convertor there is no transmission and no reception. Both LEDs TX/RX on TTL-USB convertor are on. TTL-USB convertor tested on other boards and works OK. Do I miss something?
first I enable port clocks
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOD);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOE);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOH);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
after that I see
GPIOA->AFRL - 0x00000000
GPIOA->AFRH - 0x00000000
Then after
LL_GPIO_SetAFPin_8_15(UART4_PORT, UART4_TX_PIN, LL_GPIO_AF_8);
LL_GPIO_SetAFPin_8_15(UART4_PORT, UART4_RX_PIN, LL_GPIO_AF_8);
it stays all zeroes.
GPIOA->AFRL - 0x00000000
GPIOA->AFRH - 0x00000000
I am using STOP mode to save power and also deinitialize GPIO to achieve maximum power saving. In this case current consumption goes below 1mA. I am using UART Rx pin as external interrupt to wake up board from STOP mode. The board does wake up but UART or other peripheral like DCMI doesn't work. Following is my code.
void MX_GPIO_Deinit()
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Pin = GPIO_PIN_All;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
/* Disable GPIOs clock */
__HAL_RCC_GPIOA_CLK_DISABLE();
__HAL_RCC_GPIOB_CLK_DISABLE();
__HAL_RCC_GPIOC_CLK_DISABLE();
__HAL_RCC_GPIOH_CLK_DISABLE();
}
void stopMode(void)
{
HAL_SuspendTick();
MX_GPIO_Deinit();
__HAL_RCC_PWR_CLK_ENABLE();
HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);
}
void resumeStopMode(void)
{
SystemClock_Config();
HAL_ResumeTick();
MX_GPIO_Init();
HAL_UART_MspInit(&huart4);
HAL_I2C_MspInit(&hi2c2);
HAL_DCMI_MspInit(&hdma_dcmi);
HAL_TIM_MspPostInit(&htim1);
MX_DMA_Init();
MX_UART4_Init();
MX_I2C2_Init();
MX_DCMI_Init();
MX_TIM1_Init();
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
}
int getChar()
{
uint8_t InputData = 0;
TimmingDelay = 50000;
while (TimmingDelay !=0)
{
if (__HAL_UART_GET_FLAG(&huart4, UART_FLAG_ORE))
__HAL_UART_CLEAR_OREFLAG(&huart4);
if (__HAL_UART_GET_FLAG(&huart4, UART_FLAG_RXNE))
{
InputData = huart4.Instance->DR & 0x1FF;
return InputData;
}
}
return -1;
}
void main(void)
{
stopMode()
resumeStopMode() /* woken up by uart interrupt*/
int receivedByte = 0;
receivedByte = getChar() /* This line doesn't work after waking it goes into stop mode */
}
Since I deinitialize all GPIO I am not able to to debug. How can I make UART work properly after waking up from STOP mode.
There is a wake-up latency associated with STOP mode to allow the HSI RC oscillator to wake up and potentially flash and the internal regulator. If the first byte is corrupt then it is most likely that it is a result of this latency.
This is my solution.
HAL_UART_MspInit(&huart4);
__HAL_UART_DISABLE(&huart4);
__HAL_UART_ENABLE(&huart4);
but following do not work.
HAL_UART_Init(&huart4);
I ran into almost this exact same issue and here was my solution (keep in mind I'm using UART2):
HAL_UART_MspInit(&huart2);
MX_USART2_UART_Init();
The reason that just calling the normal MX_USART2_UART_Init() function doesn't work is because the UART peripheral has state and wont re-initialize clocks if its state doesn't think it needs to:
Drivers/STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_uart.c
308 HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart)
309 {
.
.
.
327 if (huart->gState == HAL_UART_STATE_RESET)
328 {
.
.
.
343 /* Init the low level hardware : GPIO, CLOCK */
344 HAL_UART_MspInit(huart);
I'm using MBED on STM32F437 MCU (my own target) and trying to properly reach STOP mode. This MCU doesn't have LPTIM (low power timer) so I'm trying to configure RTC (or WKUP pin PA0) to wakeup MCU a few seconds after STOP. So far so good. But there is problem after wakeup. MCU is running, serial printf is working, but MBED Ticker and Timer are not running as expected. Here's the deal - Ticker doesn't call attached interrupt and Timer probably overflows after wakeup.
// mcu start
Timer t;
t.start();
Thread::wait(10000); // sleep is enabled 10 seconds after MCU is powered ON
-> t = 10002
// wakeup timer for 10 seconds configured
// stop mode enabled
// this happens after wakeup
-> t = 4294783
-> t = 4295784
-> t = 4296785
-> t = 4297786
-> t = 4298787
For wakeup i'm using this library
https://os.mbed.com/users/Sissors/code/WakeUp/
And in Stop routine, there is code like
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin : PA0 */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Allow access to Backup */
HAL_PWR_EnableBkUpAccess();
/* Disable all used wakeup sources: Pin1(PA.0) */
HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1);
/* Clear all related wakeup flags */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
/* Re-enable all used wakeup sources: Pin1(PA.0) */
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
/* FLASH Deep Power Down Mode enabled */
HAL_PWREx_EnableFlashPowerDown();
/* Enter Stop Mode */
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
/* Configures system clock after wake-up from STOP: enable HSE, PLL and select
PLL as system clock source (HSE and PLL are disabled in STOP mode) */
SetSysClock();
and this is how my clock init (SetSysClock) looks like. It's called both after MCU start and MCU wakeup.
/******************************************************************************/
/* PLL (clocked by HSE) used as System clock source */
/******************************************************************************/
uint8_t SetSysClock_PLL_HSE(uint8_t bypass)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
/* The voltage scaling allows optimizing the power consumption when the device is
clocked below the maximum system frequency, to update the voltage scaling value
regarding system frequency refer to product datasheet. */
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
// Enable HSE oscillator and activate PLL with HSE as source
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
if (bypass == 0) {
RCC_OscInitStruct.HSEState = RCC_HSE_ON; // External 8 MHz xtal on OSC_IN/OSC_OUT
} else {
RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS; // External 8 MHz clock on OSC_IN
}
RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
#if (CLOCK_SOURCE_USB)
RCC_OscInitStruct.PLL.PLLN = 336;
#else
RCC_OscInitStruct.PLL.PLLN = 336;
#endif
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // 180 MHz or 168 MHz if CLOCK_SOURCE_USB defined
RCC_OscInitStruct.PLL.PLLQ = 7;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
return 0; // FAIL
}
// Activate the OverDrive to reach the 180 MHz Frequency
if (HAL_PWREx_EnableOverDrive() != HAL_OK) {
return 0; // FAIL
}
// Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // 180 or 168 MHz
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // 45 or 42 MHz
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; // 90 or 84 MHz
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) {
return 0; // FAIL
}
// HAL_RCC_MCOConfig(RCC_MCO2, RCC_MCO2SOURCE_SYSCLK, RCC_MCODIV_3);
return 1;
}
#endif
I am trying to implement SPI on STM32F3 Discovery board using standard peripheral library. I don't want to use HAL drivers(It is a constraint). I am not able to figure what I am missing. I am implementing the SPI in slave mode. Below is the SPI configuration and code in main function.
void main() {
/* Initializes the SPI communication */
SPI_I2S_DeInit(SPIx);
SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
SPI_Init(SPIx, &SPI_InitStructure);
/* Initialize the FIFO threshold */
SPI_RxFIFOThresholdConfig(SPIx, SPI_RxFIFOThreshold_QF);
While(1){
// Start SPI transfer
/* DMA channel Rx of SPI Configuration */
DMA_InitStructure.DMA_BufferSize = NumberOfByte;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SPIx_DR_ADDRESS;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RxBuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_Init(SPIx_RX_DMA_CHANNEL, &DMA_InitStructure);
/* DMA channel Tx of SPI Configuration */
DMA_InitStructure.DMA_BufferSize = NumberOfByte;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SPIx_DR_ADDRESS;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_Init(SPIx_TX_DMA_CHANNEL, &DMA_InitStructure);
/* Enable the SPI Rx and Tx DMA requests */
SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Rx, ENABLE);
SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Tx, ENABLE);
/* Enable the SPI peripheral */
SPI_Cmd(SPIx, ENABLE);
/* Enable the DMA channels */
DMA_Cmd(SPIx_RX_DMA_CHANNEL, ENABLE);
DMA_Cmd(SPIx_TX_DMA_CHANNEL, ENABLE);
/* Wait the SPI DMA transfers complete or time out */
while (DMA_GetFlagStatus(SPIx_RX_DMA_FLAG_TC) == RESET)
{}
TimeOut = USER_TIMEOUT;
while ((DMA_GetFlagStatus(SPIx_TX_DMA_FLAG_TC) == RESET)&&(TimeOut != 0x00))
{}
if(TimeOut == 0)
{
//TimeOut_UserCallback();
count += 1;
}
/* The BSY flag can be monitored to ensure that the SPI communication is complete.
This is required to avoid corrupting the last transmission before disabling
the SPI or entering the Stop mode. The software must first wait until TXE=1
and then until BSY=0.*/
TimeOut = USER_TIMEOUT;
while ((SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET)&&(TimeOut != 0x00))
{}
if(TimeOut == 0)
{
//TimeOut_UserCallback();
count += 1;
}
TimeOut = USER_TIMEOUT;
while ((SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_BSY) == SET)&&(TimeOut != 0x00))
{}
if(TimeOut == 0)
{
//TimeOut_UserCallback();
count += 1;
}
/* Clear DMA1 global flags */
DMA_ClearFlag(SPIx_TX_DMA_FLAG_GL);
DMA_ClearFlag(SPIx_RX_DMA_FLAG_GL);
/* Disable the DMA channels */
DMA_Cmd(SPIx_RX_DMA_CHANNEL, DISABLE);
DMA_Cmd(SPIx_TX_DMA_CHANNEL, DISABLE);
/* Disable the SPI peripheral */
SPI_Cmd(SPIx, DISABLE);
/* Disable the SPI Rx and Tx DMA requests */
SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Rx, DISABLE);
SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Tx, DISABLE);
}}
SPI configuration is as follows :
static void SPI_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable the SPI peripheral */
RCC_APB2PeriphClockCmd(SPIx_CLK, ENABLE);
/* Enable the DMA peripheral */
RCC_AHBPeriphClockCmd(SPI_DMAx_CLK | TIM_DMAx_CLK, ENABLE);
/* Enable the TIM peripheral */
RCC_APB1PeriphClockCmd(TIMx_CLK, ENABLE);
/* Enable SCK, MOSI, MISO and NSS GPIO clocks */
RCC_AHBPeriphClockCmd(SPIx_SCK_GPIO_CLK | SPIx_MISO_GPIO_CLK |
SPIx_MOSI_GPIO_CLK |
SPIx_NSS_GPIO_CLK , ENABLE);
/* Enable TIM DMA trigger clock */
RCC_AHBPeriphClockCmd(TIMx_TRIGGER_GPIO_CLK, ENABLE);
/* SPI pin mappings */
GPIO_PinAFConfig(SPIx_SCK_GPIO_PORT, SPIx_SCK_SOURCE, SPIx_SCK_AF);
GPIO_PinAFConfig(SPIx_MOSI_GPIO_PORT, SPIx_MOSI_SOURCE, SPIx_MOSI_AF);
GPIO_PinAFConfig(SPIx_MISO_GPIO_PORT, SPIx_MISO_SOURCE, SPIx_MISO_AF);
GPIO_PinAFConfig(SPIx_NSS_GPIO_PORT, SPIx_NSS_SOURCE, SPIx_NSS_AF);
/* TIM capture compare pin mapping */
GPIO_PinAFConfig(TIMx_TRIGGER_GPIO_PORT, TIMx_TRIGGER_SOURCE,
TIMx_TRIGGER_AF);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* SPI SCK pin configuration */
GPIO_InitStructure.GPIO_Pin = SPIx_SCK_PIN;
GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStructure);
/* SPI MOSI pin configuration */
GPIO_InitStructure.GPIO_Pin = SPIx_MOSI_PIN;
GPIO_Init(SPIx_MOSI_GPIO_PORT, &GPIO_InitStructure);
/* SPI MISO pin configuration */
GPIO_InitStructure.GPIO_Pin = SPIx_MISO_PIN;
GPIO_Init(SPIx_MISO_GPIO_PORT, &GPIO_InitStructure);
/* SPI NSS pin configuration */
GPIO_InitStructure.GPIO_Pin = SPIx_NSS_PIN;
GPIO_Init(SPIx_NSS_GPIO_PORT, &GPIO_InitStructure);
/* Configure the TIM channelx capture compare as DMA Trigger */
GPIO_InitStructure.GPIO_Pin = TIMx_TRIGGER_PIN;
GPIO_Init(TIMx_TRIGGER_GPIO_PORT, &GPIO_InitStructure);
/* SPI configuration -------------------------------------------------------
*/
SPI_I2S_DeInit(SPIx);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_DataSize = SPI_DATASIZE;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
/* DMA Configuration -------------------------------------------------------
*/
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
}
Can anyone tell me where the problem is? I have Master code in HAL drivers on other board that is working fine(Tested). So there is no issue in master side. Slave side is the problem.
your code is in While(1) where you are configuring and initializing the SPI peripheral. make it in a separate function and initialize and configure only once. Also first try it without DMA and later put DMA back in.