CAN RX interrupt freezing on STM32 - stm32

I have a problem that my RX interrupt callback doesn't trigger after some time of running state (sometimes 30 seconds, sometimes 10 minutes...), and I don't know any more where to look for the failure.
I am using a CANopen stack from Emtas, but this stack doesn't enable nor disable interrupts according to fa. Emtas, and I am also not using IT disables. The CPU doesn't freeze; it runs in the loop even after the RX freeze.
INFO: CPU-STM32f429, EMTAS CANOpen, Atollic lite, HAL libraries.
Code flow:
while(1){
CanOpenTask();
SPI1communicatin(); // Polled
CanOpenTask();
SPI3communicatin(); // Polled
CanOpenTask();
SPI6communicatin(); // Polled
}
CAN settings:
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(CAN1_TX_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(CAN1_TX_IRQn);
HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
HAL_NVIC_SetPriority(CAN1_SCE_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(CAN1_SCE_IRQn);
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 6;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SJW = CAN_SJW_1TQ;
hcan1.Init.BS1 = CAN_BS1_12TQ;
hcan1.Init.BS2 = CAN_BS2_2TQ;
hcan1.Init.TTCM = DISABLE;
hcan1.Init.ABOM = DISABLE;
hcan1.Init.AWUM = DISABLE;
hcan1.Init.NART = DISABLE;
hcan1.Init.RFLM = DISABLE;
hcan1.Init.TXFP = DISABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK)
{
Error_Handler();
}
Where/how do I search for the reason of this problem?

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 ;(

STM32 RS485 Communication does not work as expected

I have a weight cell which replies to specific frames over RS485 (cell contains its own communication protocol). Manufacturer has a software to test the cell so I connect it to my pc using a RS485 to USB converter and I am able to connect to the cell and send/receive frames. Here are the parameters I use and you can see TX-RX frames below:
Now I want to manage this protocol with a STM32 board but I am not receiving frames properly. I am using NUCLEO-F401RE and RS485 CAN Shield from Waveshare (https://www.waveshare.com/wiki/RS485_CAN_Shield). Here is what I do and my UART configuration:
Main program
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
GPIO_InitStruct.Pin = GPIO_PIN_8;
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);
MX_USART1_UART_Init();
MX_USART2_UART_Init();
printf("NUCLEOF401RE - RS485 RX\r\n");
while (1)
{
// Activate sending status
HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 1);
txBuffer[0] = 0x44; // SOF
txBuffer[1] = 0x01; // DIR
txBuffer[2] = 0x00; // ERR
txBuffer[3] = 0x25; // CMD
txBuffer[4] = 0x00; // DATOS0
txBuffer[5] = 0x00; // DATOS1
txBuffer[6] = 0x00; // DATOS2
txBuffer[7] = 0x00; // DATOS3
txBuffer[8] = txBuffer[1] ^ txBuffer[2] ^ txBuffer[3] ^ txBuffer[4] ^ txBuffer[5] ^ txBuffer[6] ^ txBuffer[7]; // CRC
txBuffer[9] = 0x0A; // EOF
printf("TX - Sending frame\r\n");
HAL_UART_Transmit(&UART_RS485, txBuffer, framelength, 1000);
// Activate receiving status
HAL_GPIO_WritePin (GPIOA, GPIO_PIN_8, 0);
HAL_UART_Receive(&UART_RS485, rxBuffer, framelength, 1000);
printf("RX - Reception Completed:\r\n");
for(int j=0; j<framelength; j++)
{
printf("Byte %d: %02X\r\n", j, rxBuffer[j]);
}
HAL_Delay(3000);
}
UART Configuration
static void MX_USART1_UART_Init(void)
{
UART_RS485.Instance = USART1;
UART_RS485.Init.BaudRate = 115200;
UART_RS485.Init.WordLength = UART_WORDLENGTH_8B;
UART_RS485.Init.StopBits = UART_STOPBITS_1;
UART_RS485.Init.Parity = UART_PARITY_NONE;
UART_RS485.Init.Mode = UART_MODE_TX_RX;
UART_RS485.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UART_RS485.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&UART_RS485) != HAL_OK)
{
Error_Handler();
}
}
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(huart->Instance==USART1)
{
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
I should be receiving a frame starting with 0x44 and ending with 0x0A based on the cell protocol. However, this is what I receive:
I have tried many different UART parameters, many different pin configurations and tried using a 120 ohm and 220 ohm resistors between A and B lines but nothing works.
What am I missing?
I suggest you to see: Uart Status Register of you STM32 uc (because you could see UART errors like parity error, frame error and buffer overflow). In my work UART errors very often were related to buffer overflow because uc usually have a very small buffer (for ATmega 32 - 2 bytes).
Also i suggest you to use mode with parity bit, because it a data check in any case.
Also have you calculate you UART error (depends on you clock frequency and UART speed). You also could select UART speed with 0 % of errors.
You could see article about status register and baud rate here: http://www.micromouseonline.com/2009/12/31/stm32-usart-basics/

Uart doesn't work after waking up from stop mode in stm32f4

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);

STM32 MBED stop mode - timer not working after wakeup

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

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).