Displaying ADC values on a LCD display for stm32F7469I-DISCO - adc

I am working on a project where I am trying to display the brightness that an analog light sensor is measuring on a LCD on stm32F7469I-DISCO. I connected a 3.3V source to the sensor, continued with a resistor and GND, I am measuring the voltage to the A2 pin and the value on the LCD shows up as 'O'. Does anyone have any insight into this or know how to assist me?
I am using freeRTOS.
osThreadId_t lcdTaskHandle;
const osThreadAttr_t lcdTask_attributes = {
.name = "lcdTaskHandle",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
BSP_LCD_Init();
BSP_LCD_LayerDefaultInit(0, LCD_FB_START_ADDRESS);
BSP_LCD_Clear(LCD_COLOR_WHITE);
ts_status = BSP_TS_Init(BSP_LCD_GetXSize(), BSP_LCD_GetYSize());
while(ts_status != TS_OK);
ts_status = BSP_TS_ITConfig();
while(ts_status != TS_OK);
BSP_LCD_SetFont(&Font24);
BSP_LCD_SetTextColor(LCD_COLOR_BLACK);
BSP_LCD_SetBackColor(LCD_COLOR_WHITE);
BSP_LCD_SetTextColor(LCD_COLOR_DARKRED);
osKernelInitialize();
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL,
&defaultTask_attributes);
osKernelStart();
void StartLcdTask(void *argument)
{
uint16_t adc_value = 0;
float light_percentage;
char light_percentage__string[5];
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 1000);
for(;;)
{
adc_value = HAL_ADC_GetValue(&hadc1);
light_percentage = (adc_value * 100.0) / ADC_RESOLUTION6b;
BSP_LCD_DisplayStringAt(0, 0, (uint8_t *)"Light Percentage:", CENTER_MODE);
sprintf(light_percentage_string, "%.f", light_percentage);
BSP_LCD_DisplayStringAt(0, 30, (uint8_t *)light_percentage_string, CENTER_MODE);
}
}

Related

stm32 SPI receive only mode need a transmit?

sorry in advance, i am new at this kind of projects.
I tried to implement a connection to an ADC (LTC1609) via SPI. I just want to get the data from the ADC as quick as possible. The ADC has just a output-line, so i chose the "read only mode". But i also tried to use the HAL_SPI_TransmitReceive funktion because i remembered that the spi exchange starts with writeing in the transmit register (at least with the HCS12).
The ADC needs also some additional signals changes between pulling down the NSS and starting the spi connection so i put the NSS in software mode.
The Cofiguration looks like this:
static void MX_SPI1_Init(void)
{
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
}
I write a funktion to read from ADC and store the data.
void LTC1609_ADU_Read(uint8_t *data)
{
uint8_t buffer_rx[2];
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0); // NSS low (Pin PA4) Start
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, 0); // ADU R/NC low (Pin PG6) Start conversion
delay_hns (1); // wait 1us (10 x 100ns)
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, 1); // ADU R/NC high (Pin PG6)
if(HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_8) == 1) // /BUSY is high? -> start SPI
{
if(HAL_SPI_Receive(&hspi1, buffer_rx,2,10)!= HAL_OK);
{
SPI_error = HAL_SPI_GetError(&hspi1); // get the SPI error
Error_Handler(); // stop in error
}
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1); // Set ADU /CS high (Pin PA4) fin
*data = buffer_rx[1]; // store received data
}
In the while(1) i called it like this with a delay of 100 ms for testing:
LTC1609_ADU_Read(&buffer_A_rx);
Problem:
The uC (STM32L4R5ZIT6P) dont start the SPI clk to trigger out the data from ADC. Also the Clock polarity is somtimes low (like i want) and sometimes high [could also be a messuring problem, i messure it with a sheep logic analyser 24Mhz 8CH from amazon].
If i start the programm, it runs into the error handler and the errorcode is 0x20. I found this explaining:
HAL_SPI_ERROR_FLAG 0x00000020U /*!< Flag: RXNE,TXE, BSY */
Can anyone give me a tip on what could be the reason? Did iam doing something wrong or could the hardware be damaged? Thanks in advance!
screenshot signals without clk
One problem that I see in your code is that you check the BUSY pin immediately after setting R/C high and abort the transaction if BUSY is low.
According to the datasheet, BUSY line may be low for up to 3 us (t3).
Try waiting for the busy pin to go high, for example by adding a loop as shown below.
void LTC1609_ADU_Read(uint8_t *data)
{
uint8_t buffer_rx[2];
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0); // NSS low (Pin PA4) Start
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, 0); // ADU R/NC low (Pin PG6) Start conversion
delay_hns(1); // wait 1us (10 x 100ns)
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, 1); // ADU R/NC high (Pin PG6)
uint8_t retries = 0;
do {
delay_hns(1);
} while (HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_8) == 0 && ++retries < 5);
if (HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_8) == 1) // /BUSY is high? -> start SPI
{
if (HAL_SPI_Receive(&hspi1, buffer_rx, 2, 10) != HAL_OK)
{
SPI_error = HAL_SPI_GetError(&hspi1); // get the SPI error
Error_Handler(); // stop in error
}
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1); // Set ADU /CS high (Pin PA4) fin
*data = buffer_rx[1]; // store received data
}
Also, there is a stray ; in your code, on this line:
if(HAL_SPI_Receive(&hspi1, buffer_rx,2,10)!= HAL_OK);

problem with using SPI with DMA on STM32F1

I have a problem with triggering NSS pin, when transmitting SPI with DMA.
I use a CubeMX to generate whole core of project.
Time before triggering NSS to low, and sending data(also between end of transmission, and NSS to high) is too long. How can i make this times shorter?
I tried to use
HAL_DMA_PollForTransfer(&hdma_spi1_tx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
for detecting end of SPI DMA transmission but once it worked, and later when i changed something in CubeIDE it completely stoped working whole program...
int dmabusy = 0;
while (1)
{
uint8_t testing[] = {5, 10, 15, 20, 25, 30};
//HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
dmaBusy = 1;
GPIOB->BSRR = GPIO_BSRR_BS12;
HAL_SPI_Transmit_DMA(&hspi1, testing, 6);
while(dmaBusy == 1);
GPIOB->BSRR = GPIO_BSRR_BR12;
//HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
for(int i=0; i<80000; i++){ // OPOZNIACZ START
asm("NOP");
} // OPOZNIACZ STOP
}
/* USER CODE END 3 */
}
void HAL_SPI_TxCpltCallback (SPI_HandleTypeDef * hspi){
dmaBusy=0;
}

STM32F4 SPI interrupts stop firing with FreeRTOS

I'm trying to make an SPI communication between a F410 MCU and a RPi using SPI.
I post below the code that currently works (without FreeRTOS usage):
main.c
volatile int tx_done = 0;
volatile int rx_done = 0;
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
tx_done = 1;
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
rx_done = 1;
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI5_Init();
MX_USART2_UART_Init();
const uint8_t BUF_SIZE = 16 * sizeof(uint8_t);
uint8_t buf[16];
// For UART debug
uint8_t dbg_buffer[64];
while (1) {
memset(buf, 0, BUF_SIZE);
HAL_StatusTypeDef ret = HAL_SPI_Receive_IT(&hspi5, (uint8_t*)&buf, BUF_SIZE);
while (rx_done == 0) {};
rx_done = 0;
sprintf((char*) dbg_buffer, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d]\r\n",
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
buf[7], buf[8], buf[9], buf[10], buf[11], buf[12],
buf[13], buf[14], buf[15]);
HAL_UART_Transmit(&huart2, dbg_buffer, strlen((char const*) dbg_buffer), 50);
HAL_SPI_Transmit_IT(&hspi5, (uint8_t*) &buf, BUF_SIZE);
while (tx_done == 0) {};
tx_done = 0;
}
}
stm32f4xx_it.c
/**
* #brief This function handles TIM1 trigger and commutation interrupts and TIM11 global interrupt.
*/
void TIM1_TRG_COM_TIM11_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim11);
}
/**
* #brief This function handles SPI5 global interrupt.
*/
void SPI5_IRQHandler(void)
{
HAL_SPI_IRQHandler(&hspi5);
}
spi.c
/* SPI5 init function */
void MX_SPI5_Init(void)
{
hspi5.Instance = SPI5;
hspi5.Init.Mode = SPI_MODE_SLAVE;
hspi5.Init.Direction = SPI_DIRECTION_2LINES;
hspi5.Init.DataSize = SPI_DATASIZE_8BIT;
hspi5.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi5.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi5.Init.NSS = SPI_NSS_HARD_INPUT;
hspi5.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi5.Init.TIMode = SPI_TIMODE_DISABLE;
hspi5.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi5.Init.CRCPolynomial = 15;
if (HAL_SPI_Init(&hspi5) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
[...]
HAL_NVIC_SetPriority(SPI5_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(SPI5_IRQn);
}
This working fine with my test code on the other (raspberry pi) side, sending a SPI frame every second, waiting 100ms and reading the answer from the F410.
Now, when I activate FreeRTOS, I move the while(1) loop content to a task, and creates it with
BaseType_t task1 = xTaskCreate(task_1, "task_1", 512, NULL, tskIDLE_PRIORITY, &xHandle);
and osKernelStart(). I also use the TIM11 as Timebase Source (under SYS tab on CubeMX as advised by the software itself)
Then I have the following behavior: If I place breakpoints inside both Tx/Rx SPI interrupt, I found that a couple (3-4 ?) of them are fired, then never again. If I stop my code I see I'm stucked in the
while (rx_done == 0) {};
loop, confirming that I don't get SPI RX interrupts anymore whereas there is still frame coming on the SPI bus.
To dig a little into that theory, I made another test with this in my task:
while(1) {
memset(buf, 0, 16);
HAL_StatusTypeDef ret = HAL_SPI_Receive_IT(&hspi5, (uint8_t*)&buf, 16);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
// Wait for RX interrupt, task is suspended to give processing time to (incoming) others tasks
vTaskSuspend(NULL);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
}
and in my Rx interrupt, I simply call
xTaskResumeFromISR(task1Handle);
With this code, the first packet sent is read correctly by the STM32F4, and task print it on USART2 and suspend itself again. From then, (checked with a breakpoint inside), the Rx interrupt is never called again, so the task resume inside neither, and my code is frozen...
It really looks like there is a messing between FreeRTOS and STM32 HAL SPI/interrupt handling ?
Any help will be gladly accepted !
Do you call NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 ); as described in the red text on this page: https://www.freertos.org/RTOS-Cortex-M3-M4.html ?
If you are using an STM32 with the STM32 driver library then ensure all the priority bits are assigned to be preempt priority bits by calling NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 ); before the RTOS is started.

STM32F4 Discovery

I have STM32F4 Discovery. I use IAR embedded Workbench. I am new to this kit. I want to measure distance. my code does not give an error. the distance is always zero. What could be the error? please help me . thanks everyone
#include "stm32f4_discovery.h"
#include "delay.h"
uint32_t Read_Distance(void);
void Init();
uint32_t distance ;
int main()
{
Init(); // initialisation de pin
SysTick_Init(); // pour pouvoire utiliser la fonction delay :)
while (1)
{
distance=Read_Distance();
delay_nms(100);
}
}
void Init()
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_InitTypeDef gpioStructure;
gpioStructure.GPIO_Pin = GPIO_Pin_10;
gpioStructure.GPIO_Mode = GPIO_Mode_OUT;
gpioStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOD, &gpioStructure);
gpioStructure.GPIO_Pin = GPIO_Pin_11;
gpioStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_Init(GPIOD, &gpioStructure);
}
//Les Pins pour le Test sont PD10 (Trig) et PD11(echo)
uint32_t Read_Distance(void)
{
__IO uint8_t flag=0;
__IO uint32_t disTime=0;
GPIO_SetBits(GPIOD,GPIO_Pin_10);
delay_nus(10);
GPIO_ResetBits(GPIOD,GPIO_Pin_10);
while(flag == 0)
{
while(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11) == SET)
{
disTime++;
flag = 1;
}
}
return disTime;
}
Looks like you're using one of those ultrasonic distance measurement modules
Try this:
while(flag == 0)
{
disTime++;
if(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11) == SET)
{
flag = 1;
}
}
You should use one of the hardware timers to get a more accurate time measurement.
Now I've had time to think more about it I remember now that you get a pulse sent back with a width proportional to the distance. I think this is the correct answer:
// Wait for pulse to start
while (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11) == RESET)
{
NOP;
}
// Measure pulse width
while(flag == 0)
{
disTime++;
// Has pulse ended
if(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_11) == RESET)
{
flag = 1;
}
}
You may also want to tackle the case where the pulse is never received because this could will block forever.
If I understand correctly, D10 is wired to D11 and you want to check how long your signal remains high. If this is the case, you should increment a counter in timer interrupt handler when your pin is high and reset that counter variable once you've read it.

arduino not writing to sd card

I have an Arduino with a Seeedstudio sd card shield v4.0 with a prototpye shield above that, and on that is a TMP36 temperature sensor and a red and two green LEDs, the red to show that it is "Ready" to log data, the first green to show that it is currently "logging data" and the last LED to show that the data was "Saved" to the SD card, which it dosent, at the beggining of the file, however, it creates the line "Testing 1, 2, 3..." in a txt file called TEST. in that same file there should be the data, but there is no data, it will write to the card in setup, but not in loop. Can anyone help me?
Code:
#include <toneAC.h>
#include <SPI.h>
#include <SD.h>
int readyLED = 2;
int startLED = 8;
int buzzer = 7;
int tempSensor = A0;
int readyButton = 5;
int sampleNo = 0;
int button_mode = 1;
int saveLED = 4;
File myFile;
void setup() {
// put your setup code here, to run once:
pinMode(readyLED, OUTPUT);
digitalWrite(readyLED, HIGH);
pinMode(saveLED, OUTPUT);
digitalWrite(saveLED, LOW);
pinMode(startLED, OUTPUT);
pinMode(buzzer, OUTPUT);
pinMode(10, OUTPUT);
pinMode(tempSensor, INPUT);
pinMode(readyButton, INPUT);
digitalWrite(readyLED, HIGH);
digitalWrite(startLED, LOW);
Serial.begin(9600);
while (!Serial){}
Serial.println("Initializing SD card...");
if(!SD.begin(4)){
Serial.println("Failed!");
return;
}
Serial.println("Success!");
myFile = SD.open("test.txt", FILE_WRITE);
if (myFile) {
Serial.println("Writing to test.txt...");
myFile.println("testing 1, 2, 3.");
delay(500);
myFile.close();
Serial.println("done.");
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(readyLED, HIGH);
digitalWrite(startLED, LOW);
delay(700);
digitalWrite(startLED, HIGH);
delay(650);
int reading = analogRead(tempSensor);
float voltage = reading * 5.0;
voltage /= 1024.0;
float temperatureC = (voltage - 0.5) * 100;
float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
Serial.print("Sample No. ");
sampleNo = sampleNo + 1;
Serial.print(sampleNo);
Serial.print(" Temperature: ");
Serial.print(temperatureF);
Serial.println(" F");
myFile = SD.open("test.txt", FILE_WRITE);
if(myFile){
Serial.println("Test.txt");
}
while(myFile.available()){
myFile.print("Sample No. ");
myFile.print(sampleNo);
myFile.print(" Temperature: ");
myFile.print(temperatureF);
myFile.println(" F");
}
delay(30);
digitalWrite(saveLED, HIGH);
delay(10);
digitalWrite(saveLED, LOW);
delay(10);
myFile.close();
}
You may want to check to make sure your while loop is actually being run. Since you know you can write to the SD card from void setup() you know your code inside the while loop works, but is the while loop actually being run, or is it evaluating to false and being skipped?
Have you considered the time it takes to write down data as an issue? You may be asking for it write down data before the Arduino code has time to process.