STM32 - RS485 request-response - stm32

I am trying to send request to measuring device and receive it's response using UART with interrupts. However communication is unstable, I am receiving incomplete or corrupted responses. I am not sure but I think it's because switching driver enable signal. Could you look at my code and give me some advice what am I doing wrong?
Here is my code:
int main(void){
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART3_UART_Init();
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET); //RS 485 transmit mode
while (1)
{
if(HAL_UART_Transmit_IT(&huart3, (uint8_t*)aTxBuffer, 2) != HAL_OK)
{
while(1);
}
while (UartReady != SET);
UartReady = RESET;
if(HAL_UART_Receive_IT(&huart3, (uint8_t*)aRxBuffer, 4) != HAL_OK)
{
while(1);
}
while (UartReady != RESET);
//do somethink with received data
}
}
Here are my callback functions:
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle)
{
/* Set transmission flag: transfer complete */
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET); //RS 485 receive mode
//DataRecieved = 0;
UartReady = SET;
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
/* Set transmission flag: transfer complete */
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET); //RS 485 transmit mode
//DataRecieved = 1;
UartReady = SET;
}
Thank you very much

The data you transmit, does it also appear at your RX-buffer, while you expect it not to?

I am receiving incomplete or corrupted responses. I am not sure but I
think it's because switching driver enable signal. Could you look at
my code and give me some advice what am I doing wrong?
Not sure, but maybe it would help to toggle the DE pin not in the interrupt callback functions, and instead switch to "transmit mode" right before invoking HAL_UART_Transmit_IT() and then to switch back to receive mode after the transmission, or even after calling HAL_UART_Receive_IT(), to make sure it will catch the incoming bytes. Tiny delays do matter sometimes:
void set_transmit_mode(void)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET); // RS 485 transmit mode
}
void set_receive_mode(void)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET); // RS 485 receive mode
}
{
//...
set_transmit_mode();
if (HAL_UART_Transmit_IT(&huart3, (uint8_t*)aTxBuffer, 2) != HAL_OK) {
// ...
}
while (UartReady != SET);
//set_receive_mode();
UartReady = RESET;
if (HAL_UART_Receive_IT(&huart3, (uint8_t*)aRxBuffer, 4) != HAL_OK) {
// ...
}
set_receive_mode();
while (UartReady != RESET);
//...
}

Related

CMSIS_driver I2C problem, status stuck in busy

I tried to learn the CMSIS driver in I2C. I have STM32F407VGT6 and EEPROM at24c256 as test hardware. First, create the I2C environment with CubeMX to config the I2C.
https://imgur.com/CbroTeo
https://imgur.com/nCP5eFt
then I followed the arm example from the arm-cmsis driver website.
https://arm-software.github.io/CMSIS_5/Driver/html/group__i2c__interface__gr.html
#include "Driver_I2C.h"
#define EEPROM_I2C_ADDR 0xA0 /* EEPROM I2C address */
/* I2C driver instance */
extern ARM_DRIVER_I2C Driver_I2C1;
static ARM_DRIVER_I2C *I2Cdrv = &Driver_I2C1;
static volatile uint32_t I2C_Event;
/* I2C Signal Event function callback */
void I2C_SignalEvent (uint32_t event) {
/* Save received events */
I2C_Event |= event;
/* Optionally, user can define specific actions for an event */
if (event & ARM_I2C_EVENT_TRANSFER_INCOMPLETE) {
/* Less data was transferred than requested */
}
if (event & ARM_I2C_EVENT_TRANSFER_DONE) {
/* Transfer or receive is finished */
}
if (event & ARM_I2C_EVENT_ADDRESS_NACK) {
/* Slave address was not acknowledged */
}
if (event & ARM_I2C_EVENT_ARBITRATION_LOST) {
/* Master lost bus arbitration */
}
if (event & ARM_I2C_EVENT_BUS_ERROR) {
/* Invalid start/stop position detected */
}
if (event & ARM_I2C_EVENT_BUS_CLEAR) {
/* Bus clear operation completed */
}
if (event & ARM_I2C_EVENT_GENERAL_CALL) {
/* Slave was addressed with a general call address */
}
if (event & ARM_I2C_EVENT_SLAVE_RECEIVE) {
/* Slave addressed as receiver but SlaveReceive operation is not started */
}
if (event & ARM_I2C_EVENT_SLAVE_TRANSMIT) {
/* Slave addressed as transmitter but SlaveTransmit operation is not started */
}
}
/* Read I2C connected EEPROM (event driven example) */
int32_t EEPROM_Read_Event (uint16_t addr, uint8_t *buf, uint32_t len) {
uint8_t a[2];
a[0] = (uint8_t)(addr >> 8);
a[1] = (uint8_t)(addr & 0xFF);
/* Clear event flags before new transfer */
I2C_Event = 0U;
I2Cdrv->MasterTransmit (EEPROM_I2C_ADDR, a, 2, true);
/* Wait until transfer completed */
while ((I2C_Event & ARM_I2C_EVENT_TRANSFER_DONE) == 0U);
/* Check if all data transferred */
if ((I2C_Event & ARM_I2C_EVENT_TRANSFER_INCOMPLETE) != 0U) return -1;
/* Clear event flags before new transfer */
I2C_Event = 0U;
I2Cdrv->MasterReceive (EEPROM_I2C_ADDR, buf, len, false);
/* Wait until transfer completed */
while ((I2C_Event & ARM_I2C_EVENT_TRANSFER_DONE) == 0U);
/* Check if all data transferred */
if ((I2C_Event & ARM_I2C_EVENT_TRANSFER_INCOMPLETE) != 0U) return -1;
return 0;
}
/* Read I2C connected EEPROM (pooling example) */
int32_t EEPROM_Read_Pool (uint16_t addr, uint8_t *buf, uint32_t len) {
uint8_t a[2];
a[0] = (uint8_t)(addr >> 8);
a[1] = (uint8_t)(addr & 0xFF);
I2Cdrv->MasterTransmit (EEPROM_I2C_ADDR, a, 2, true);
/* Wait until transfer completed */
while (I2Cdrv->GetStatus().busy);
/* Check if all data transferred */
if (I2Cdrv->GetDataCount () != len) return -1;
I2Cdrv->MasterReceive (EEPROM_I2C_ADDR, buf, len, false);
/* Wait until transfer completed */
while (I2Cdrv->GetStatus().busy);
/* Check if all data transferred */
if (I2Cdrv->GetDataCount () != len) return -1;
return 0;
}
/* Initialize I2C connected EEPROM */
int32_t EEPROM_Initialize (bool pooling) {
int32_t status;
uint8_t val;
if (pooling == true) {
I2Cdrv->Initialize (NULL);
} else {
I2Cdrv->Initialize (I2C_SignalEvent);
}
I2Cdrv->PowerControl (ARM_POWER_FULL);
I2Cdrv->Control (ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST);
I2Cdrv->Control (ARM_I2C_BUS_CLEAR, 0);
/* Check if EEPROM can be accessed */
if (pooling == true) {
status = EEPROM_Read_Pool (0x00, &val, 1);
} else {
status = EEPROM_Read_Event (0x00, &val, 1);
}
return (status);
}
above was the code example from cmsis-driver website. I have modified the EEPROM_I2C_ADDR to 0xA0(for AT24C256 EEPROM).
then I try to run main() with function
EEPROM_Initialize(true)
then this function will get into EEPROM_Read_Pool()
but the test always stuck in
while (I2Cdrv->GetStatus().busy);
after I2Cdrv->MasterTransmit (EEPROM_I2C_ADDR, a, 2, true);。
I have tried
use HAL library to run MEM_Write, MEM_Read with the EEPROM, and make sure the EEPROM could work.
HAL_I2C_Mem_Write(&hi2c1, EEPROM_ADDRESS, 0, 0xff, &data_to_write, 1,10);
HAL_Delay(10);
uint8_t data_read = 60;
HAL_I2C_Mem_Read(&hi2c1,EEPROM_ADDRESS,0,0xff,&data_to_read,1,1);
I have checked the return value of all below
I2Cdrv->PowerControl (ARM_POWER_FULL);
I2Cdrv->Control (ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST);
I2Cdrv->Control (ARM_I2C_BUS_CLEAR, 0);
I2Cdrv->MasterTransmit (EEPROM_I2C_ADDR, a, 2, true);
all the return value are 0x00000000(seems running ok).But still have no idea why the status is always busy.
I have checked that it has no chance to get into the
I2C_EV_IRQHandler or I2C_ER_IRQHandlerin debug mode to change the status or increase the TX count.

Individually read distinct inputs with STM32L ADC

The goal is to read multiple ADC channels by polling. It does not need to be fast - the idea is to read the voltages from different batteries that are attached. I have a STM32L071 microcontroller. The programming is a bit different compared to the STM32F0 model. I am using platformio.
I found already very helpful information here:
Individually read distinct inputs with STM32F0 ADC
https://controllerstech.com/stm32-adc-multiple-channels/
https://deepbluembedded.com/stm32-adc-tutorial-complete-guide-with-examples/
However, unfortunately I cannot read out multiple channels. The problems are probably related to HAL_ADC_Init and HAL_ADC_ConfigChannel.
Here is a minimal code example:
#include <Arduino.h>
#include <STM32IntRef.h>
uint32_t a1=0, a2=0;
#define HAL_ADC_MODULE_ENABLED
ADC_HandleTypeDef hadc1;
void displaying(){
Serial.println("values:");
Serial.println("-------");
Serial.print("ch1 - ");
Serial.println(a1);
Serial.print("ch2 - ");
Serial.println(a2);
Serial.println("");
}
void config_ext_channel_ADC(uint32_t channel, bool val) {
hadc1.Instance = ADC1;
hadc1.Init.SamplingTime = ADC_SAMPLETIME_79CYCLES_5;
HAL_ADC_Init(&hadc1);
ADC_ChannelConfTypeDef sConfig;
sConfig.Channel = channel;
if (val == true) {
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
} else {
sConfig.Rank = ADC_RANK_NONE;
}
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
Serial.println("Error ADC Config Channel");
//Error_Handler();
}
}
uint32_t r_single_ext_channel_ADC(uint32_t channel) {
/* read the ADC and output result */
uint32_t digital_result;
config_ext_channel_ADC(channel, true);
HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 1000);
digital_result = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
config_ext_channel_ADC(channel, false);
return digital_result;
}
void readBat() {
/* read voltages */
a1 = r_single_ext_channel_ADC(1);
a2 = r_single_ext_channel_ADC(PA2);
}
void setup() {
// put your setup code here, to run once:
// Serial monitor
Serial.begin(9600);
Serial.println(F("Starting now"));
// initialize pins for ADC
analogReadResolution(ADC_RESOLUTION);
pinMode(PA1, INPUT);
//pinMode(BATTERY_SENSE_PIN2, INPUT);
pinMode(PA2, INPUT_ANALOG);
}
void loop() {
// put your main code here, to run repeatedly:
readBat();
displaying();
delay(2000);
}
The output is:
values:
-------
ch1 - 0
ch2 - 140
Sounds reasonable, but applying some voltages at the pins does not change the values.
Could somebody please provide me some advice, ideas?
Okay, in the meantime I found the problem. The software is fine; I took the Arduino framework and used analogRead().
I needed to clean all the solder flux from the PCB which caused some contacts between the pins.
Moreover, if one wants to use address the HAL directly, one should set the ClockDivider such that the ADC samples below 1 MHz.
Code to read different ADC channels (here ADC2 with 2 channels) separetly (Generated By CubeMX):
Note: We have to use ScanConvMode plus DiscontinuousConvMode and NO ContinuousConvMode.
/* ADC2 init function */
void MX_ADC2_Init(void)
{
/* USER CODE BEGIN ADC2_Init 0 */
/* USER CODE END ADC2_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC2_Init 1 */
/* USER CODE END ADC2_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc2.Instance = ADC2;
hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc2.Init.Resolution = ADC_RESOLUTION_12B;
hadc2.Init.ScanConvMode = ENABLE;
hadc2.Init.ContinuousConvMode = DISABLE;
hadc2.Init.DiscontinuousConvMode = ENABLE;
hadc2.Init.NbrOfDiscConversion = 1;
hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc2.Init.NbrOfConversion = 2;
hadc2.Init.DMAContinuousRequests = DISABLE;
hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
if (HAL_ADC_Init(&hadc2) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_8;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_9;
sConfig.Rank = 2;
if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC2_Init 2 */
/* USER CODE END ADC2_Init 2 */
}
Now, to read:
void readChannel(){
//read the next channel
HAL_ADC_Start(&hadc2);
uint8_t ret = HAL_ADC_PollForConversion(&hadc2, 1000 /*timeout*/);
uint16_t value = HAL_ADC_GetValue(hadc);
printf("HAL_ADC_PollForConversion status: %d, VALLLL: %d\n", ret, value);
}
int main(){
while(1){
//Automatically read the first channel (channel 8):
readChannel();
HAL_Delay(100);
//Automatically read the second channel (channel 9):
readChannel();
HAL_Delay(100);
}
}
Did you miss to set the io to analog in mode? It should be something like this somewhere (usually in your hal msp file, adc_init func).
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
edit => you missed it for ch1
analogReadResolution(ADC_RESOLUTION);
pinMode(PA1, INPUT);
//pinMode(BATTERY_SENSE_PIN2, INPUT);
pinMode(PA2, INPUT_ANALOG);
It should be the same as PA2, input is "digital mode".

I can't get data with I2C from mpu6050 on STM32F103

I am new I2C communication. I examined some running code. And I used function their used. But I can't get any data. I wonder if I2C have to do initial config? Where is the problem. This is function I wrote:
void GetI2CAccelerometer(uint8_t slaveAddress,uint8_t accelData[6])
{
// slaveAddress=0x68 (default address is written in datasheet)
HAL_I2C_Master_Transmit(&hi2c1,slaveAddress<<1,1,0x3B,1,200);
HAL_I2C_Master_Receive(&hi2c1,slaveAddress<<1,accelData,6,200);
HAL_I2C_Mem_Read(&hi2c1,(slaveAddress<<1)+1,0x3B,1,accelData,1,200);
// i tried this function too but not working
}
I created this project with CubeMX. This is initial I2C config and also GPIO_A clock line is activated in another function which I did not write:
static void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 208;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
}
First of all, better use DMA or IT data exchange. Polling is not good, but ok for testing.
You must put pointers to data, not the data itself. The good practice is something like this:
void GetI2CAccelerometer(I2C_HandleTypeDef * hi2c, uint8_t slaveAddress, uint8_t * accelData, size_t size) {
uint8_t request = 0x3B;
// slaveAddress=0x68 (default address is written in datasheet)
// HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
while (HAL_I2C_Master_Transmit(hi2c, slaveAddress << 1, (uint8_t*)request, 1, 200) != HAL_OK) {
// Use FreeRTOS vTaskDelay(1) and/or check errors here
// And check timeout or you will hang over here
}
//HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
while (HAL_I2C_Master_Receive(hi2c, slaveAddress << 1, accelData, size, 200) != HAL_OK) {
// Use FreeRTOS vTaskDelay(1) and/or check errors here
// And check timeout or you will hang over here
}
while (HAL_I2C_GetState(hi2c) != HAL_I2C_STATE_READY) {
// Use FreeRTOS vTaskDelay(1) and/or check errors here
// And check timeout or you will hang over here
}
}
And then request data by function:
uint8_t accelData[6];
GetI2CAccelerometer(&hi2c1, 0x68, accelData, 6);
Thats ok for testing, but bad for production. Get the data and then rewrite to use I2C DMA or IT. Check errors at I2C bus and make some enum to return errors/states from function.

Why "HAL_I2C_Master_Transmit" writes 2 bytes of data in each loop

I'm using HAL library for stm32f4 (V1.7.1) and trying to understand how HAL_I2C_Master_Transmit works. This function transmits a "master to slave" packet on SDA line.
In the stm32f4xx_hal_i2c.c code after sending slave address there is a loop (while(hi2c->XferSize > 0U)) that sends bytes which we want to be transmitted to slave. This loop works until all bytes are transmitted. But there is a question that "why the function wants to transmit TWO bytes in each loop?" There is an IF in loop (if((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U))) that checks if the previous byte is currently transferred then send the the next byte!
I don't know what is the reason of existing this IF when in the next loop other bytes can be transmitted?!
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t
DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
uint32_t tickstart = 0x00U;
/* Init tickstart for timeout management*/
tickstart = HAL_GetTick();
if(hi2c->State == HAL_I2C_STATE_READY)
{
/* Wait until BUSY flag is reset */
if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET,
I2C_TIMEOUT_BUSY_FLAG, tickstart) != HAL_OK)
{
return HAL_BUSY;
}
/* Process Locked */
__HAL_LOCK(hi2c);
/* Check if the I2C is already enabled */
if((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE)
{
/* Enable I2C peripheral */
__HAL_I2C_ENABLE(hi2c);
}
/* Disable Pos */
hi2c->Instance->CR1 &= ~I2C_CR1_POS;
hi2c->State = HAL_I2C_STATE_BUSY_TX;
hi2c->Mode = HAL_I2C_MODE_MASTER;
hi2c->ErrorCode = HAL_I2C_ERROR_NONE;
/* Prepare transfer parameters */
hi2c->pBuffPtr = pData;
hi2c->XferCount = Size;
hi2c->XferOptions = I2C_NO_OPTION_FRAME;
hi2c->XferSize = hi2c->XferCount;
/* Send Slave Address */
if(I2C_MasterRequestWrite(hi2c, DevAddress, Timeout, tickstart) != HAL_OK)
{
if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
{
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_ERROR;
}
else
{
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_TIMEOUT;
}
}
/* Clear ADDR flag */
__HAL_I2C_CLEAR_ADDRFLAG(hi2c);
while(hi2c->XferSize > 0U)
{
/* Wait until TXE flag is set */
if(I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
{
if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
{
/* Generate Stop */
hi2c->Instance->CR1 |= I2C_CR1_STOP;
return HAL_ERROR;
}
else
{
return HAL_TIMEOUT;
}
}
/* Write data to DR */
hi2c->Instance->DR = (*hi2c->pBuffPtr++);
hi2c->XferCount--;
hi2c->XferSize--;
if((__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) && (hi2c->XferSize != 0U))
{
/* Write data to DR */
hi2c->Instance->DR = (*hi2c->pBuffPtr++);
hi2c->XferCount--;
hi2c->XferSize--;
}
/* Wait until BTF flag is set */
if(I2C_WaitOnBTFFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK)
{
if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)
{
/* Generate Stop */
hi2c->Instance->CR1 |= I2C_CR1_STOP;
return HAL_ERROR;
}
else
{
return HAL_TIMEOUT;
}
}
}
/* Generate Stop */
hi2c->Instance->CR1 |= I2C_CR1_STOP;
hi2c->State = HAL_I2C_STATE_READY;
hi2c->Mode = HAL_I2C_MODE_NONE;
/* Process Unlocked */
__HAL_UNLOCK(hi2c);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}

I2c communication stm32f3 how can i solve?

i want to read touch activity from the touchscreen.If i touch, i want to led blink. Some my definitions in below code but generally i want to get my activity with i2c
Some definitions:
uint8_t deviceaddr;
static uint32_t touch_i2c_read(uint8_t DeviceAddr, uint8_t RegAddr, uint8_t *pBuffer, uint16_t len);
static const int I2C_TIMEOUT = 65536;
unsigned char i2c_buffer[256];
uint32_t res;
This is my i2c read code:
static uint32_t touch_i2c_read(uint8_t DeviceAddr, uint8_t RegAddr, uint8_t *pBuffer, uint16_t len)
{ //uint8_t deviceaddr ,0x00,(uint8_t *)&buf, sizeof(buf)
uint32_t timeout = I2C_TIMEOUT;
while (I2C_GetFlagStatus(I2C1, I2C_ISR_BUSY) != RESET)
{
if ((timeout--) == 0)
return 0;
}
I2C_TransferHandling(I2C1, DeviceAddr << 1, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
/* !!! Wait until TXIS flag is set !!! */
timeout = I2C_TIMEOUT;
while (I2C_GetFlagStatus(I2C1, I2C_ISR_TXIS) == RESET)
{
if ((timeout--) == 0)
return 0;
}
}
This is my settings
void configure_interrupt_pins()
{
GPIO_InitTypeDef GPIO_InitStruct;
EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
/*ENABLE CLOCK FOR GPIOX*/
RCC_APB1PeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
// ENABLE CLOCK FOR SYSCFG
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
//SET PIN AS INPUT
// init_pin(EX_NCVIC_PORT, EX_NCVIC_Pin, GPIO_MODE_INPUT, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP);
//TELL THE SYSTEM THAT YOU WILL USE PXX FOR EXTI_LineX
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOx, EXTI_PinSourcex);
//CONFIGIRATION of exti
EXTI_InitStruct.EXTI_Line = EXTI_Linex; //pxx connect to line x
EXTI_InitStruct.EXTI_LineCmd = ENABLE; //enable interrupt
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; //interrupt mode
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //triggers on rising and failing edge
EXTI_Init(&EXTI_InitStruct); //add to exti
//CONFIGURATION of nvic
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
This is my interrupt
void EXTI0_IRQHandler(void)
{
if (EXTI_GetITStatus((EXTI_Line0) != RESET))
{
res = touch_i2c_read(0x42, 0x00, i2c_buffer, 22);
printf("deneme");
if (!res)
{
GPIO_SetBits(GPIOE, GPIO_Pin_13);
}
else
{
GPIO_SetBits(GPIOE, GPIO_Pin_13);
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
But my code not working. Stm32 dont understand touch activity how can i solve this.
Edit i change line 1 every external interupts but i have res value 0 how can i fix this it must be different 0
Using a while() loop in an interrupt will cause problems, because the controller will never exit the loop. Try to use your i2c read Function in main() (with other words, a not-interrupt-context) and look if it works there.
I solved this error.
I hadn't any signal pb7 and pb6 so i changed codes as below:
// enable APB1 peripheral clock for I2C1
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
// enable clock for SCL and SDA pins
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
And then,
Device adress of the FT6236 was mising. it is not include at datasheet so i used debugging. I found the device adress which is the (0x32). And than my code working succesfully.