program freezes when calling I2C write function - c

Board : STM32F4 Discovery
I am having troubles initializing I2C, i think! When the program reaches I2C_write function it hangs! I am trying to communicate with a temp&hum sensor HDC1080 from TI. The hardware is ok, i've been testing it with cubeMX and HAL libraries and it works ok!
I have a saleae logic analyzer hooked up to PB8(SCL) and PB9(SDA) , there's no activity!
I removed the init_usart part thinking that maybe they are interffering because they share the same port (GPIOB).
void init_usart(void)
{
//enable AHB1 peripheral clock
RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOB, ENABLE);
//Init GPIOB
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);
//Enable USART peripheral clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
//Init usart
USART_InitTypeDef USART_InitStruct;
USART_InitStruct.USART_BaudRate = 57600;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No ;
USART_InitStruct.USART_Mode = USART_Mode_Tx;
USART_InitStruct.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
USART_Init(USART1, &USART_InitStruct);
USART_Cmd(USART1, ENABLE);
}
void InitializeI2C()
{
RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; // 8=SCL 9=SDA
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1);
/* enable APB1 peripheral clock for I2C1*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);
I2C_InitTypeDef I2C_InitStruct;
I2C_InitStruct.I2C_ClockSpeed = 100000;
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStruct.I2C_OwnAddress1 = 0x01;
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStruct);
I2C_Cmd(I2C1, ENABLE);
}
void I2C_write( uint8_t HW_address, uint8_t addr, uint8_t data)
{
I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, HW_address, I2C_Direction_Transmitter);
while (!I2C_CheckEvent(I2C1,
I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2C1, addr);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, data);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C1, ENABLE);
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
}
int main(void)
{
init_usart()
InitializeI2C();
while (1)
{
delay_div(50);
I2C_write( 0x40 << 1 , 0x01, 0x00); //here it stops!!!
}

One possible problem: You are using uninitialised data.
From your code:
I2C_InitTypeDef I2C_InitStruct;
I2C_InitStruct.I2C_ClockSpeed = 100000;
//I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStruct.I2C_OwnAddress1 = 0x01;
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStruct);
At least I2C_Mode is not initialised here, and you cannot assume the value to be 0. It will just be whatever is on the stack at that time.
You either want to memset the struct to 0, or implicitly initialise other members to zero when declaring:
I2C_InitTypeDef I2C_InitStruct = {
.I2C_ClockSpeed = 100000,
//.I2C_Mode = I2C_Mode_I2C,
.I2C_DutyCycle = I2C_DutyCycle_2,
.I2C_OwnAddress1 = 0x01,
.I2C_Ack = I2C_Ack_Enable,
.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit,
};
I2C_Init(I2C1, &I2C_InitStruct);

My temp & hum sensor is dead! I2C init is fine, tried it with an i2c oled display and i can see activity on the bus!
Just a short and final update!!! Bear with me, please!
My temp&hum sensor (HDC1080) was ok! After spending 40 minutes soldering wires to a new sensor (the pins are 0.4mm) i discovered that this was also not working.
Nothing changed in terms of hardware from my succesfull initial test that i did using the HAL library, breadboard with 2 x 10k (that's what i had) pull-up resistors, 3V power supply from stm32 discovery board.
It seems that for unknown reasons the HAL test was working with those two 10k pull-ups but the SP library wasn't. Since my SSD1306 oled display comes on a pcb with 4.7k resistors already mounted i was able to discover that i can communicate with both the temp&hum sensor and display.
Final conclusion , pull-up resistors was my problem in the end!

Related

STM32F4 multiple SPI_I2S_GetFlagStatus crashes the program

I'm trying to implement a simple http server on my stm32F411RE nucleo board from here, but of course I've run into some problems - so far, I managed to narrow the current one to the fact, that after about 20 calls to
SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE); My program crashes. By crash, I mean goes to the Infinite Loop defined in the startup file, reason being "Program received signal SIGINT, Interrupt."
My spi is initialised like that:
void SPI1_Init(void){
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable SPI1 and GPIOA clocks */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
//SCK, MISO, MOSI
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//CS
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//CS down
GPIO_SetBits(GPIOA, GPIO_Pin_2);
SPI_InitTypeDef SPI_InitStructure;
/* SPI1 configuration */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI1, &SPI_InitStructure);
/* Enable SPI1 */
SPI_Cmd(SPI1, ENABLE);
}
after the initialization, I do this:
for(tmpCnt = 0; tmpCnt < 100; tmpCnt++){
SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE);
}
and it crashes after about 20 iterations. I am using the standard peripheral library, and System Workbench with all stock settings of compiler and everything else. At the moment nothing is connected to the SPI pins, could that be the problem?
calling
(SPI1->SR) instead of SPI_I2S_GetFlagStatus
has the same effect so I guess that the problem lies withing reading the register. Why could that be? I'm really stuck at the moment, so any help would be appreciated.
EDIT:
Ok, it turns out that I missed a bit of code that seems to cause this behaviour - before the SPi1->SR calls, I also had this function called:
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
SysTick->LOAD = ticks - 1; /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */
SysTick->VAL = 0; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0); /* Function successful */
}
why does it break the SPI1->SR access? could there be anything else wrong? My main function:
int main(void)
{
int tmpCnt = 0;
int rev = 0;
//uint16_t writedat = 22;
RCC_Init();
SPI1_Init();
//SysTick_Config(1000);
for(tmpCnt = 0; tmpCnt < 50; tmpCnt++){
SPI1->SR ;
}
enc28j60Init((unsigned char *)enc28j60_MAC);
//simple_server();
rev = enc28j60getrev();
return rev;
}
RCC_Init does not seem to change anything in the behaviour of the SPI1->SR.
As before, any advice would be welcome.

STM32F1 timer share for PWM and interrupt

i'm implementing a project using stm32f101cb microcontroller. I understand that this control have 3 timer in it. TIM2 and TIM4 had been set to encoder mode to capture 2 rotary encoder.
I'm now left me the only timer TIM3, I would to ask is there possible for me to set TIM3 to PWM mode and at the same time doing the normal timer interrupt? I could not find it in reference manual or programming manual.
Thanks!
It should be possible. I'm doing it for an STM32F091RC I've developed an application for where I'm controlling LED:s with PWM and generating a timer update interrupt (counter reset) with the same timer peripheral.
Here's some of my configuration code:
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* LED_TIM clock enable */
RCC_APB1PeriphClockCmd(TIM_LED_RCC, ENABLE);
/* LED_PORT Configuration: Channel 1, 2, 3 as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = LED_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(LED_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(LED_PORT, LED_PIN_SOURCE, LED_TIM_AF);
/* Enable the TIM global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = LED_TIM_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Time Base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = LED_TIM_PSC;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // Max 0xFFFF
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* Channel 1 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_Pulse = LED_INIT_PULSE;
TIM_OC1Init(LED_TIM, &TIM_OCInitStructure); // Init Channel 1
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);
/* TIM IT enable */
TIM_ITConfig(LED_TIM, TIM_IT_Update, ENABLE); // Enable interrupts for LED_TIM
/* LED_TIM counter enable */
TIM_Cmd(LED_TIM, ENABLE);
/* LED_TIM Main Output Enable */
TIM_CtrlPWMOutputs(LED_TIM, ENABLE);
Should be very similar for your device. If everything works correctly, you should be getting interrupts in your TIM3_IRQHandler ISR
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(LED_TIM, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(LED_TIM, TIM_IT_Update);
// Do ISR stuff here!
}
}

STM32F407 UART gives garbage on terminal

I have just started my adventures with STM32f407 Discovery board. I'm using latest stable release of CoIDE and using up to date toolchain/libraries.
I managed to write the following code in order to use USART1 from the board
int main(void){
GPIO_InitTypeDef GPIO_InitStructure; // Definicja struktury do inicjalizacji PINOW
USART_InitTypeDef USART_InitStructure;
// Initialize pins as alternating function
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
// Modify USART_InitStructure for non -default values , e.g.
// USART_InitStructure.USART_BaudRate = 38400;
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
USART_Init(USART1 ,&USART_InitStructure);
USART_Cmd(USART1 , ENABLE);
while(1)
{
while (USART_GetFlagStatus(USART1 , USART_FLAG_TXE) == RESET);
USART1 ->DR = (uint16_t)(45 & 0x01FF);
Delay(0x3FFFFF);
}
}
Also I have made sure clock is configured correctly by setting HSE and other clock details
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
And also
/************************* PLL Parameters *************************************/
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M 8
#define PLL_N 336
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P 2
/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */
#define PLL_Q 7
/******************************************************************************/
In console I just receive garbage and I have made the following to make sure the setup is correct :
- Checked USB-RS232 converter
- Switched between converter and STM32 board
- Switched converter
- Generated code using STM32CubeMX to compare it and it seems consistent (logic wise of course :) )
From my beginner perspective it is kinda "showstopper" :( I cannnot seem to find a root cause of this
Any help would be appreciated
UPDATE 1 : In order to find root cause I have decided to try one of the other USART modules. Below is my code for USART3 and this one WORKS OUT OF THE BOX which would lead me to incorrect init of USART1 in the initial question ?
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
/* Enable GPIO clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
/* Enable UART clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
/* Connect PXx to USARTx_Tx*/
GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);
/* Connect PXx to USARTx_Rx*/
GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);
/* Configure USART Tx as alternate function */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* Configure USART Rx as alternate function */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_Init(GPIOC, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* USART configuration */
USART_Init(USART3, &USART_InitStructure);
/* Enable USART */
USART_Cmd(USART3, ENABLE);
SysTick_Config(SystemCoreClock / 1000);
while(1)
{
for (int var = 45; var < 128; var++)
{
USART_SendData(USART3, var);
Delay_SysTick(500); // 1 sek
}
}
}
Resolution: After a lot of digging and trying multiple things it appears that USART1 would collide with USB components and there is capacitor which collides with the transmission link to answer on ST forums
I wish I would have found this somewhere in documentation before.
Hope this helps someone and thanks everyone for your assistance
USART1 on this board (TX pin) has capacitor which collides with traffic. It is mentioned on ST forums.
Garbage on terminal often is caused when the sender has a different baudrate than the receiver.

STM32F407 SPI reciveing only 0xFF (255) or 0

Recently I have been trying to receive a data from my STM32F407 motion sensor. I have the following code:
uint8_t SPI1_Read(){
GPIO_ResetBits(GPIOA, GPIO_Pin_4); // CS low
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET){}
SPI_I2S_SendData(SPI1, 0x00);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)==RESET){}
return SPI_I2S_ReceiveData(SPI1);
}
void SPI1_Write(uint8_t data){
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET){}
SPI_I2S_SendData(SPI1, data);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET){}
SPI_I2S_ReceiveData(SPI1);
}
volatile static int vrednost, vrednost1, vrednost2;
int main(void)
{
// Vkljuci driver za GPIOD
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
// Nastavi registre za LED diode
GPIO_InitTypeDef inicializacijskaStruktura;
inicializacijskaStruktura.GPIO_Mode = GPIO_Mode_OUT;
inicializacijskaStruktura.GPIO_OType = GPIO_OType_PP;
inicializacijskaStruktura.GPIO_PuPd = GPIO_PuPd_NOPULL;
inicializacijskaStruktura.GPIO_Speed = GPIO_Speed_100MHz;
inicializacijskaStruktura.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOD, &inicializacijskaStruktura);
SPI_and_GPIO_Init();
// init
SPI1_Write(0x20);
SPI1_Write(0x47);
SPI1_Write(0x0F);
SPI1_Write(0xBC);
while(1)
{
SPI1_Write(0x20);
vrednost=SPI1_Read();
SPI1_Write(0x24);
vrednost1=SPI1_Read();
SPI1_Write(0x28);
vrednost2=SPI1_Read();
if(vrednost<122){
GPIO_SetBits(GPIOD, GPIO_Pin_12);
}
else{
GPIO_ResetBits(GPIOD, GPIO_Pin_12);
}
if(vrednost1<122)
GPIO_SetBits(GPIOD, GPIO_Pin_13);
else
GPIO_ResetBits(GPIOD, GPIO_Pin_13);
if(vrednost2<122)
GPIO_SetBits(GPIOD, GPIO_Pin_14);
else
GPIO_ResetBits(GPIOD, GPIO_Pin_14);
}
}
void SPI_and_GPIO_Init(){
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable the SPI periph */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
/* Enable SCK, MOSI and MISO GPIO clocks */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA , ENABLE);
/* Enable CS GPIO clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);
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 pins configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* SPI configuration -------------------------------------------------------*/
SPI_I2S_DeInit(SPI1);
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
/* Enable SPI1 */
SPI_SSOutputCmd(SPI1, ENABLE);
SPI_Cmd(SPI1, ENABLE);
/* Configure GPIO PIN for Lis Chip select */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/* Deselect : Chip Select high */
GPIO_SetBits(GPIOE, GPIO_Pin_3);
}
Upper code works fine, but the problem is that always when I try to read motion sensor, i get 0xFF or in another words 255. I read data by sending dummy text and then read data.
I have been also given an advice to set Slave Select pin (SS) to zero, but I don't know how to do that.
Does anybody know?
To hazard a guess - typically with SPI, SS is driven low (enable) at the start of each write/read then driven high (disable) at the end of each write/read to indicate end of transmission. Without pulling out the board, that's what I'd bet on.
If that's not it - ST is pretty good at providing examples. The source code on their product page includes an example using their MEMs accelerometer (Utilities/STM32F4-Discovery/stm32f4_discovery_lis302dl.c/.h).

synchronous mode of usart(spi mode) in stm32

I am working with the following evaluation board: SZWB-sail, STM32f103VET6 KIT v3.1
I want to use the stm32f103 usart in synchronous mode, and I used
STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\USART\Synchronous
I modified the code in an attempt to use USART2/SPI1, as opposed to the working code provided via STMicro, which uses USART1/SPI1.
The README for this example states that:
"USARTy and SPIy can be USART1 and SPI1 or USART2 and SPI3, depending on the STMicroelectronics EVAL board you are using."
Despite this, I attempted to physically connect USART2 Tx/Rx/Ck pins (PA2,PA3,PA4) to SPI1 SCK/MISO/MOSI (PA5,PA6,PA7). Is there a software reason for why this won't work? Or might it be hardware connections on the eval board?
Here is my code:
int main(void)
{
SystemInit();
Init_NVIC();
/* System Clocks Configuration */
RCC_Configuration();
/* Configure the GPIO ports */
GPIO_Configuration();
SPI_Configuration();
USART_Configuration();
while(NbrOfDataToRead2--)
{
USART2_Send_Byte(TxBuffer1[TxCounter1++]);
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET)
{
}
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)
{
}
RxBuffer2[RxCounter2++] = SPI_I2S_ReceiveData(SPI1);
}
USART2_Receive_Byte();
while(NbrOfDataToRead1--)
{
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)== RESET)
{
}
SPI_I2S_SendData(SPI1, TxBuffer2[TxCounter2++]);
USART2_Send_Byte(DYMMY_BYTE);
while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET)
{
}
while(USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET)
{
}
RxBuffer1[RxCounter1++] = USART2_Receive_Byte();
}
TransferStatus1 = Buffercmp(TxBuffer1, RxBuffer2, TxBufferSize1);
TransferStatus2 = Buffercmp(TxBuffer2, RxBuffer1, TxBufferSize2);
while(1)
{
}
}
void Init_NVIC(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void RCC_Configuration(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE );
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 , ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure1,GPIO_InitStructure2;
GPIO_InitTypeDef GPIO_InitStructure3,GPIO_InitStructure4,GPIO_InitStructure5,GPIO_InitStructure6;
/* Configure USART1 Rx as input floating */
GPIO_InitStructure1.GPIO_Pin =GPIO_Pin_10;
GPIO_InitStructure1.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure1);
/* Configure USART1 Tx as alternate function push-pull */
GPIO_InitStructure2.GPIO_Pin =GPIO_Pin_9;
GPIO_InitStructure2.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure2);
/* Configure USART2 Rx as input floating */
GPIO_InitStructure3.GPIO_Pin =GPIO_Pin_3;
GPIO_InitStructure3.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure3.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure3);
/* Configure USART2 Tx as alternate function push-pull */
GPIO_InitStructure4.GPIO_Pin =GPIO_Pin_2;
GPIO_InitStructure4.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure4.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure4);
/* Configure USART2 Ck as alternate function push-pull */
GPIO_InitStructure5.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure5.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure5.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure5);
/* Configure SPI1 pins: SCK, MISO and MOSI */
GPIO_InitStructure6.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_Init(GPIOA, &GPIO_InitStructure6);
}
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure1,USART_InitStructure2;
USART_ClockInitTypeDef USART_ClkInitStructure;
USART_InitStructure1.USART_BaudRate = 115200;
USART_InitStructure1.USART_WordLength =USART_WordLength_8b ;
USART_InitStructure1.USART_StopBits = USART_StopBits_1;
USART_InitStructure1.USART_Parity = USART_Parity_No;
USART_InitStructure1.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure1.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Configure USART1 */
USART_Init(USART1,&USART_InitStructure1);
//USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
/* Enable the USART1 */
USART_Cmd(USART1,ENABLE);
USART_ClkInitStructure.USART_Clock=USART_Clock_Enable;
USART_ClkInitStructure.USART_CPOL=USART_CPOL_High;
USART_ClkInitStructure.USART_CPHA=USART_CPHA_2Edge;
USART_ClkInitStructure.USART_LastBit=USART_LastBit_Enable;
USART_ClockInit(USART2, &USART_ClkInitStructure);
USART_InitStructure2.USART_BaudRate = 115200;
USART_InitStructure2.USART_WordLength =USART_WordLength_8b ;
USART_InitStructure2.USART_StopBits = USART_StopBits_1;
USART_InitStructure2.USART_Parity = USART_Parity_No;
USART_InitStructure2.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure2.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Configure USART2 */
USART_Init(USART2,&USART_InitStructure2);
//USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
/* Enable the USART2 */
USART_Cmd(USART2,ENABLE);
}
void SPI_Configuration(void)
{
SPI_InitTypeDef SPI_InitStructure;
SPI_StructInit(&SPI_InitStructure);
SPI_I2S_DeInit(SPI1);
/* SPIy Config */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;
/* Configure SPIy */
SPI_Init(SPI1, &SPI_InitStructure);
SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_RXNE,ENABLE);
/* SPIy enable */
SPI_Cmd(SPI1, ENABLE);
}
You are mixing polling mode with interrupt mode. This SPI configuration code is intended for SPI interrupt mode. Hence, SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) should not be used, because this is a function intended for Polling-Mode.
Instead, I believe you can use SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT); in conjunction with SPI_I2S_ReceiveData(SPI_TypeDef* SPIx) and SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT) (to clear any potential Error pending bits, just in-case).
Also, you might want to post your USART2_Send_Byte() code so we know what exactly it's doing, and whether it's calling any other functions...but go ahead and try this first to see if it fixes your problem.
SPI1 conflicts with USART2 synchronization mode.
SPI2 conflicts with USART3 synchronization mode.
There is no conflict between SPI1/2 and USART1 synchronization modes.

Resources