I2C STM32F4 (slave) no acknowledge bit responded - i2c

Hopefully anyone is able to help me with my problem.
I'm currently setting um a I2C bus with a FT2232H as master and a STM32F407VGT6 (Discovery-Board) as a slave. I was able to send the slave address correctly from the master but I'm not sure if the slave is setup correctly because I dont get any ACK bit as a response from the slave. I was looking over the settings quite some times.
The start and stop conditions are sent correctly aswell.
Here is my code for the slave setup:
I2C_InitTypeDef i2c_init;
NVIC_InitTypeDef NVIC_InitStructure, NVIC_InitStructure2;
I2C_DeInit(I2C1);
I2C_SoftwareResetCmd(I2C1, ENABLE);
I2C_SoftwareResetCmd(I2C1, DISABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
gpio_init.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8;
gpio_init.GPIO_Mode = GPIO_Mode_AF;
gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
gpio_init.GPIO_PuPd = GPIO_PuPd_UP;
gpio_init.GPIO_OType = GPIO_OType_OD;
GPIO_Init(GPIOB, &gpio_init);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1); // SDA
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1); // SCL
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure2.NVIC_IRQChannel = I2C1_ER_IRQn;
NVIC_InitStructure2.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure2.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure2.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure2);
I2C_ITConfig(I2C1, I2C_IT_EVT, ENABLE);
I2C_ITConfig(I2C1, I2C_IT_ERR, ENABLE);
I2C_ITConfig(I2C1, I2C_IT_BUF, ENABLE);
i2c_init.I2C_ClockSpeed = 50000;
i2c_init.I2C_Mode = I2C_Mode_I2C;
i2c_init.I2C_DutyCycle = I2C_DutyCycle_2;
i2c_init.I2C_OwnAddress1 = 0x21;
i2c_init.I2C_Ack = I2C_Ack_Enable;
i2c_init.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &i2c_init);
I2C_StretchClockCmd(I2C1, ENABLE);
I2C_Cmd(I2C1, ENABLE);
And the address I'm sending should be correct like that.
Thanks for your help :)
Edit:
The problem might also be that the STM32F4 isn't reading the I2C lines. But If thats the case I have no idea which setting is wrong. Or do I need to start the peripheral in any way? I thought if the PE bit is set the I2C is running and responding automatically. Isn't that the case?

Finally solved the problem. The default HAL Initialisation has initialized the GPIOs alternate function wrong.
There were two Pins to choose for SDA and SCL lines. For SDA in the end both pins where configured as alternate function what caused to listening on wrong line or responding to the wrong one.
Hope that helps someone else too.

Related

I cannot access STM32 DMA register when configuring it

I currently use standard peripheral library to write a driver that enable memory to USART6_TX DMA transfer on a STM32 F407 ZGT6 chip. However, I tried for a long time but the initialization keeps on failing: DMA_GetCmdStatus always returns DISABLE. By using GDB, I found that after the DMA_Init try to write configuration into DMA register, DMA CR register remains 0. The DMA initialize code and execution are as follow:
void DMA_USART6_Init(char* DMA_Start_Pos, uint32_t DMA_Buffer_Size){
DMA_Buffer_Size_GV = DMA_Buffer_Size;
DMA_Start_Pos_GV = DMA_Start_Pos;
/*RCC config*/
RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_DMA2, ENABLE);
/*DMA init*/
//DMA_DeInit(DMA2_Stream7);
DMA_Cmd(DMA2_Stream7, DISABLE);
while ((DMA_GetCmdStatus(DMA2_Stream7) == ENABLE)){}
DMA_StructInit(&DMA_InitStruct);
DMA_InitStruct.DMA_Channel = DMA_Channel_5;
DMA_InitStruct.DMA_PeripheralBaseAddr = USART6_BASE + 0x04;//(uint32_t)&USART6->DR;
DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t) dubuff;//(uint32_t) DMA_Start_Pos;
DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStruct.DMA_BufferSize = (uint16_t)sizeof(dubuff);//DMA_Buffer_Size;
printf("buffer size should be %d \r\n", (uint16_t)sizeof(dubuff));
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular;
DMA_InitStruct.DMA_Priority = DMA_Priority_High;
DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_Init(DMA2_Stream7, &DMA_InitStruct);
printf("data counter after init %d \r\n", DMA_GetCurrDataCounter(DMA2_Stream7));
}
for the ENABLE code
void DMA_USART6_Enable_DMA(char* DMA_Start_Pos, uint32_t DMA_Buffer_Size, int MB){
Max_Buffer = MB;
USART6_init_for_DMA();
DMA_USART6_Init(DMA_Start_Pos, DMA_Buffer_Size);
DMA_USART6_NVIC_Init();
DMA_ITConfig(DMA2_Stream7, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA2_Stream7, ENABLE);
while ((DMA_GetCmdStatus(DMA2_Stream7) == DISABLE)){}//program stucked in this loop
}
for the USART6 code:
void USART6_init_for_DMA(void){
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_USART6);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_USART6);
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 57600;//115200;
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_Init(USART6, &USART_InitStructure);
USART_Cmd(USART6, ENABLE);
USART_DMACmd(USART6, USART_DMAReq_Tx, ENABLE);
}
and the GDB result:
the value that should be written into DMA CR register
text in the picture 1:
367 DMAy_Streamx->CR = tmpreg;
(gdb) print tmpreg
$7 = 167904576
the DMA CR register remains 0
text in the picture2:
371 tmpreg = DMAy_Streamx->FCR;
(gdb) print *DMAy_Streamx
$10 = {CR = 0, NDTR = 0, PAR = 0, M0AR = 0, M1AR = 0, FCR = 0}
Please tell me if there is anything I can provide about my problem or things I can try further...
Note: In the same program, my USART6 and GPIO works fine.
When the desired stream is activated, the relevant registers can no longer be configured. Only in dual buffer mode can memory addresses 0 and 1 be updated according to the bit CT function. You must first deactivate the relevant channel and then apply the changes.
I am OP.
At the start, I have a feeling that it could be an obvious mistake and that's true.
It turns out that I should use RCC_AHB1PeriphClockCmd instead of RCC_AHB1PeriphResetCmd because OBVIOUSLY the later accessed RSTR (RCC Reset register) rather than ENR an thus clock is not enable (about that Codo is right).
Well, Hope guys whoever sees this question won't repeat this embarrass mistake ;(

Issue using UART with STM32F0Discovery and Fingerprint Scanner

I am currently working on a project that involves the STM32f0Discovery board and this fingerprint scanner, which uses UART communication. To initialize the UART, I do the following:
void init_uart(void){
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_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;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
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_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
}
Then to send/receive a byte I do the following:
void writechar(char c) {
while((USART1 -> ISR & USART_ISR_TC) != USART_ISR_TC);
USART1 -> TDR = c;
}
char readchar(void) {
return USART_ReceiveData(USART1);
}
To test this, I sent the OPEN command byte-by-byte through a for-loop, then the LEN-ON command the same method, which has no results. When reading for an ACK after the OPEN command, the results read are just an empty array of char bytes.
So, my question is, is my initialization the error? Or is the error in the reading/writing? Or could it be something else altogether?
Are you getting the ACK response ? If you are not then there is probably a configuration or wiring problem. I would suggest you try connecting the serial pins to a serial-usb converter
(FTDI such as this :Click here)
and use an app like Putty or YAT to send commands (ACK) to and from your stm. Try using the same configuration the scanner has if that doesn't work its a problem with your config if it does work its a problem scanner side.

how to implement SPI on STM32F3 board using standard peripheral library?

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.

STM32F4-Discovery SPI LIS3DSH

I was able to use the code below to init the SPI and read the values from accelerometer
SPI_InitTypeDef SPI_InitTypeDefStruct;
GPIO_InitTypeDef GPIO_InitTypeDefStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE , ENABLE);
SPI_InitTypeDefStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitTypeDefStruct.SPI_Mode = SPI_Mode_Master;
SPI_InitTypeDefStruct.SPI_DataSize = SPI_DataSize_8b;
SPI_InitTypeDefStruct.SPI_CPOL = SPI_CPOL_High;
SPI_InitTypeDefStruct.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitTypeDefStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;
SPI_InitTypeDefStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //seems like it was here causing trouble
SPI_InitTypeDefStruct.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_Init(SPI1, &SPI_InitTypeDefStruct);
GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_6;
GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitTypeDefStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitTypeDefStruct);
GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_3;
GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitTypeDefStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
GPIO_Init(GPIOE, &GPIO_InitTypeDefStruct);
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_SetBits(GPIOE, GPIO_Pin_3);
SPI_Cmd(SPI1, ENABLE);
SPI_send(0x23, 0xc9); // resetting the accelerometer internal circuit
//SPI_send(0x20, 0x67); // 100Hz data update rate, block data update disable, x/y/z enabled
SPI_send(0x20, 0x97);
//SPI_send(0x24, 0x20); // Anti aliasing filter bandwidth 800Hz, 16G (very sensitive), no self-test, 4-wire interface
SPI_send(0x24, 0x00); // Anti aliasing filter bandwidth 800Hz, 2G ( sensitive ??), no self-test, 4-wire interface
SPI_send(0x10, 0x00); // Output(X) = Measurement(X) - OFFSET(X) * 32;
SPI_send(0x11, 0x00); // Output(Y) = Measurement(Y) - OFFSET(Y) * 32;
SPI_send(0x12, 0x00); // Output(Z) = Measurement(Z) - OFFSET(Z) * 32;
void SPI_send(uint8_t address, uint8_t data)
{
GPIO_ResetBits(GPIOE, GPIO_Pin_3);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, address);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
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);
GPIO_SetBits(GPIOE, GPIO_Pin_3);
}
uint8_t SPI_read(uint8_t address)
{
GPIO_ResetBits(GPIOE, GPIO_Pin_3);
address = 0x80 | address; // 0b10 - reading and clearing status
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, address);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
SPI_I2S_ReceiveData(SPI1);
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);
GPIO_SetBits(GPIOE, GPIO_Pin_3);
return SPI_I2S_ReceiveData(SPI1);
}
Then I combined these code with my project which has an 500Hz interrupt.
It always work at first but if i unplug the board then plug it in again, SPI will only read zeros, even though the LIS3DSH still have readings(i used oscilloscope checked it). I had to download the shorter version of the project code( taking out most of the code in the interrupt) to get SPI to work properly again.
I am using the Kickstart, size-limited IAR ewarm I thought it was because my code exceed the limit. But I did not get warning and my code was not more than 32kb.
I am just confused since it works until I unplug it. Could someone give me some suggestions?
Thanks
I decided just to add the SPI_DeInit(...) before SPI_Init(...). This seems to solve the problem. I still dont understand why it wont reset itself though.

STM32 how to set a slave I2C port

I have an issue with STM32F0 Discovery.
I am using I2C1 (like master) to send start condition and address to I2C2 (slave) on the same board.
I am able to generate propertly the signal but the IC2 (slave) is not able to generate an ACK on 9th clk
What's wrong?
Here my code about the setup:
void set_I2C(void){
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
/* Configure the I2C clock source. The clock is derived from the HSI */
RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_1);
//Configure pins: SCL and SDA ------------------
GPIO_InitStructure.GPIO_Pin = 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_NOPULL;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_DeInit(I2C1);
I2C_Cmd(I2C1, DISABLE);
I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStructure.I2C_DigitalFilter = 0x00;
I2C_InitStructure.I2C_OwnAddress1 = 0x40;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_Timing =0xB0420F13; //100KHz
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
//Set up of I2C2
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_1);
//Configure pins: SCL and SDA ------------------
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_DeInit(I2C2);
I2C_Cmd(I2C2, DISABLE);
I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Disable;
I2C_InitStructure.I2C_DigitalFilter = 0x00;
I2C_InitStructure.I2C_OwnAddress1 = 0x30;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_Timing =0xB0420F13;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C2, &I2C_InitStructure);
I2C_Cmd(I2C2, ENABLE);
I2C_ITConfig(I2C2, I2C_AcknowledgedAddress_7bit, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the I2C2 interrupt priority */
NVIC_InitStructure.NVIC_IRQChannel = I2C2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority=1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
I had the same problem. It was caused by absence of the required for I2C external pull-up resistors. You can't just use an internal MCU's pull-ups. You MUST use external ones.
Detailed explanation is provided in these articles:
http://www.robot-electronics.co.uk/acatalog/I2C_Tutorial.html
https://electronics.stackexchange.com/questions/1849/is-there-a-correct-resistance-value-for-pull-up-resistors
I run into similar issue.
In my case the solution was to add a HAL_I2C_EnableListen_IT() after initialization to activate I2C slave (I am using HAL libraries, but you can check what the above function does in details).