STM32,Reading ADC Value and Transmitting using UART (HAL Library) - c

I am new user of STM32(L476RG).I've done some work with Arduino so far. Now,I want to read ADC Value and transmit this value with UART. I setup hardware part and initial software configuration part. I want to know, this part of code in while loop is correct?
if (HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK)
{
ADCValue = HAL_ADC_GetValue(&hadc1);
sprintf(str, "%d", ADCValue);
HAL_UART_Transmit(&huart2,ADCValue,1,100);
}

Assuming that you callHAL_ADC_Start(&hadc1) before entering the while loop.
Basically it is OK to call you code in a while loop, but I have some remarks.
Make sure that ADCValue variable is uint32_t or at least uin16_t as the return value of HAL_ADC_GetValue is uint32_t. If the ADC's resolution is above 8 bit then 1 byte won't be enough to store the result.
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
The HAL_UART_Transmit expects an uint8_t* as a second parameter, given your code you pass a simple variable. You should use the & operator before ADCValue and cast it to uint8_t*. Also it only sends 1 byte in your code, based on the third parameter. If ADCValue is uint32_t then you should modify this parameter to 4. Also note that you send raw byte value and not ASCII. All in all:
uint32_t ADCValue;
if (HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK)
{
ADCValue = HAL_ADC_GetValue(&hadc1);
sprintf(str, "%d", ADCValue);
HAL_UART_Transmit(&huart2, (uint8_t*)(&ADCValue), 4, 100);
}
(&ADCValue) returns the address of ADCValue which is an uint32_t* so it should be casted to uint8_t* when passing to HAL_UART_Transmit. And as an uint32_t is 4 byte, third param should be 4.
If you want to send the str you should calculate its correct length before sending as well.
By the way here is an ADC example from this STM32 HAL ADC Tutorial.
uint32_t g_ADCValue;
int g_MeasurementNumber;
int main(void)
{
HAL_Init();
SystemClock_Config();
ConfigureADC();
HAL_ADC_Start(&g_AdcHandle);
for (;;)
{
if (HAL_ADC_PollForConversion(&g_AdcHandle, 1000000) == HAL_OK)
{
g_ADCValue = HAL_ADC_GetValue(&g_AdcHandle);
g_MeasurementNumber++;
}
}
}

What I did as the simplest working solution was to force an ADC reset:
HAL_StatusTypeDef stat = HAL_ADC_PollForConversion(&hadc1, 900);
if (stat != HAL_OK) {
HAL_ADC_Stop(&hadc1);
HAL_ADC_Start(&hadc1);
}
This should be executed earlier than just before GetValue, I had improper action then.
P.S. Sorry for poor visibility
Slightly more elegant would be stopping after GetValue function, yet I left this code as properly working.

Related

STM32 HAL_CRC 16 Bit

I try to use the HAL_CRC on my STM32L4 in order to calculate a 16 bit CRC, but somehow I always get the same result no matter what the input is...
The CRC init
hcrc.Instance = CRC;
hcrc.Init.CRCLength = CRC_POLYLENGTH_16B; //as I have a 16bit polynome
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;
hcrc.Init.GeneratingPolynomial = 0x1021; //MCRF4xx polynome
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE; //I want to init with 0xFFFF
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE; //input inversion
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE; //output inversion
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES; //I have byte input
if (HAL_CRC_Init(&hcrc) != HAL_OK)
{
Error_Handler();
}
and then the calculation is called with
uint32_t result;
uint8_t pBuffer[3] = {0x33, 0x33, 0x55};
result = HAL_CRC_Calculate(&hcrc,pBuffer,3);
but the result is always 0xe000ed04, I'd expect 0xC91B for this specific case but at least it should change if a change the input. Does anyone spot an issue with this code snippet? I couldn't find any sample codes for 16bit CRC with the HAL Library.
I'm aware that the return value of HAL_CRC_Calculate() is a uint32_t, so my result would be the two lower bytes - in this case 0xed04. At least that's my interpretation of the function description.
The documentation indicates that you need to enable the CRC hardware clock with __HAL_RCC_CRC_CLK_ENABLE();. Are you doing that?

I2C-dev problem when accessing to ICM20948

I'm configuring a ICM20948 breakout from primo roni via i2c on a Beagle Bone black, using a minimal linux build using buildroot, via a C program. To do so, i've used this driver for the i2c connection and also this ICM20948 driver as base for the speciffic device, so the target is to merge both.
I've been able to configure some registers (like the sleepmode o lowpowermode) but when setting the fullscale, the values seems not to be changing.
This is more or less the function that pressents the problem
uint16_t set_values(uint16_t register, uint16_t value)
{
unsigned char rxBuffer[1]; // receive buffer
unsigned char txBuffer[2]; // transmit buffer
retval |= ICM_20948_set_bank(2); // Must be in the right bank
txBuffer[0] = register;
retval |= write(device.i2cHandle,txBuffer,1); // device.i2cHandle is the handler obtained when
retval |= read(device.i2cHandle,rxBuffer,1); // opening the /dev/i2c-X
printf("Readed value %x: %x\n",txBuffer[0],rxBuffer[0]);
txBuffer[1] = value;
printf("Intending to write: %x\n", txBuffer[1]);
retval |= write(device.i2cHandle, txBuffer, sizeof(txBuffer));
write(device.i2cHandle,txBuffer,1);
read(device.i2cHandle,rxBuffer,1);
printf("Written value on register %x: %x\n",txBuffer[0],rxBuffer[0]);
}
But the output when doing trying to modify the 0x14 register with the value 0x03 returns what follows:
Readed value 14: 1
Intending to write: 3
Written value on register 14: 1
Any suggestion? Thanks in advance!

Why elements in an array elements shift?

I am using stm32f4. In my project, i have one transmitter and one receiver.
i transmit an 2 byte integer value using
HAL_UART_Transmit(&huart1,&temp_byte1,sizeof(temp_byte1), 500);
HAL_UART_Transmit(&huart1,&temp_byte2,sizeof(temp_byte2), 500);
and on the receiver part. i read these values using
uint8_t temp_data[2];
uint8_t rx_data;
uint8_t rx_index=0;
uint16_t temp;
void USART6_IRQHandler(void)
{
HAL_UART_Receive_IT(&huart6,&rx_data,1);
temp_data[rx_index]=rx_data;
rx_index++;
if(rx_index==2)
{
rx_index=0;
temp = ((temp_data[0]<<8)|temp_data[1]);
if(temp!=79){ //sometimes i see a 79 in my buffer!
hc05_flag = 3; //irrelevant flag with this question
nm=0; //irrelevant flag with this question
}
}
it works fine for one time. but after, i see temp_data[1] in temp_data[0]. it shift 8 bits and i see a big temp value (63744 etc.) . where is the problem?
Assume you are transmitting integer data via UART, In HAL_UART_Transmit you are just passing address of buffer, inside it will be transmitted byte by byte so total 20 bytes will be transmitted.
uint16_t txBuffer[10] = {0xFF11,2,3,4,5,6,7,8,9,10};
HAL_UART_Transmit(&huart1,(uint8_t *) &txBuffer,sizeof(txBuffer), 500);
At Receiver - blocking
uint16_t rxBuffer[10];
void USART6_IRQHandler(void)
{
HAL_UART_Receive(&huart6,&rxBuffer,20,500);
}
At Receiver - Non-blocking
uint16_t rxBuffer[10];
void USART6_IRQHandler(void)
{
HAL_UART_Receive_IT(&huart6,&rxBuffer,20);
}
NOTE: In non blocking mode please ensure that reception is over before proceed ahead to use received data because HAL_UART_Receive_IT just trigger the interrupt and the copy operation shall be carried out in ISR routine. You can also implement received_done flag to ensure the reception is over.

Array's data is changed if I don't printf it

I am writing a C program on Eclipse to communicate from my ARM Cortex M4-F microcontroller in I2C with its master, another MCU.
In my I2C library, I use a static global variable to store all the parameters of the communication (address, lenghts, data buffers). The issue is that a part (an array containing the data to be transmitted, which are 8 bits integers) of this variable gets modified when the interrupt (Start condition followed by the slave's address on the I2C bus) happens, even before executing the code I put the handler. It gets assigned to 8, whatever the initial value.
I tried to put breakpoints basically everywhere, and a watchpoint on the variable, the changes arises seemingly from nowhere, not in the while loop, and before the call to my_I2C_Handler(), so the interrupt is the cause apparently.
I also tried setting the variable as volatile, but that changed nothing.
I noticed one interesting thing: putting a printf of the array's data during my_I2C_Init() or my_SlaveAsync(), like so:
printf("%d\n", req.tx_data[0]);
corrects this problem, but why? I want to remove all prints after debugging.
#include <stdint.h>
#include "my_i2c.h"
void I2C1_IRQHandler(void)
{
printf("\nI2C Interrupt\n");
my_I2C_Handler(MXC_I2C1); // MXC_I2C1 is a macro for the registry used
}
int main(void)
{
int error = 0;
printf("\nStarting I2C debugging\n");
// Setup the I2C
my_I2C_Shutdown(MXC_I2C1);
my_I2C_Init(MXC_I2C1);
NVIC_EnableIRQ(I2C1_IRQn); // Enable interrupt
my_I2C_SlaveAsync(MXC_I2C1); // Prepare to receive communication
while (1)
{
LED_On(0);
LED_Off(0);
}
printf("\nDone testing\n");
return 0;
}
The structure of the request containing the parameters of the communication is like this:
typedef struct i2c_req i2c_req_t;
struct i2c_req {
uint8_t addr; // I2C 7-bit Address
unsigned tx_len; // Length of tx data
unsigned rx_len; // Length of rx
unsigned tx_num; // Number of tx bytes sent
unsigned rx_num; // Number of rx bytes sent
uint8_t *tx_data; // Data for mater write/slave read
uint8_t *rx_data; // Data for master read/slave write
};
Is declared like so in the beginning of the file:
static i2c_req_t req;
and assigned this way in my_I2C_Init():
uint8_t rx[1] = {0};
uint8_t tx[1] = {12};
req.addr = 0xAA;
req.tx_data = tx;
req.tx_len = 1;
req.rx_data = rx;
req.rx_len = 1;
req.tx_num = 0;
req.rx_num = 0;
Many thanks for your help

Why OR every SPI register of the SX1272 with 0x80

I use a library from GitHub that gives the functionality to read and write to the register of the SX1272 with SPI.
It works great but i dont understand why the Lora_write_ref() function OR's every register with 0x80.
So when lets say I want to write to the Register FIFO (RegFifo) on address 0X00. I can't because the functions Or's the register with 0X80.
I know that what I think is wrong because it works just fine but why?
Code from https://github.com/Inteform/esp32-lora-library
/**
* Write a value to a register.
* #param reg Register index.
* #param val Value to write.
*/
void
lora_write_reg(int reg, int val)
{
uint8_t out[2] = { 0x80 | reg, val };
uint8_t in[2];
spi_transaction_t t = {
.flags = 0,
.length = 8 * sizeof(out),
.tx_buffer = out,
.rx_buffer = in
};
gpio_set_level(CONFIG_CS_GPIO, 0);
spi_device_transmit(__spi, &t);
gpio_set_level(CONFIG_CS_GPIO, 1);
}
According to SX1272/73 datasheet it is part of the SPI interface for writing the registers:
The first byte is the address byte. It is comprises:
A wnr bit, which is 1 for write access and 0 for read access.
Then 7 bits of address, MSB first.

Resources