В настоящее время я использую «STM32F429I-DISC1» с джойстиком. Я пытаюсь что-то нарисовать на ЖК-экране и с помощью джойстика перемещаю этот объект. Мой рисунок работает нормально, но у меня есть ошибка: "пустое значение не игнорируется, как должно быть".
У этих двух строк есть проблемы...
localX = Joy_ReadXY(CTRL_REG_IN3);
localY = Joy_ReadXY(CTRL_REG_IN4);
Может кто-нибудь, пожалуйста, скажите мне, как я могу исправить эту ошибку?
И почему я вижу эту ошибку?
Main.c
#include "stm32f429i_discovery_lcd.h"
#define CTRL_REG_IN3 0b00011000
#define CTRL_REG_IN4 0b00100000
SemaphoreHandle_t xMutex;
Joystick_data xy;
void vTaskFunction1(void *pvParameters) {
uint16_t localX;
uint16_t localY;
for(;;) {
localX = Joy_ReadXY(CTRL_REG_IN3);
localY = Joy_ReadXY(CTRL_REG_IN4);
xSemaphoreTake( xMutex, portMAX_DELAY );
xy.x = localX;
xy.y = localY;
xSemaphoreGive( xMutex );
HAL_Delay(10);
}
}
void vTaskFunction2(void *pvParameters) {
uint32_t xCoord = 240/2;
uint32_t yCoord = 320/2;
uint8_t reads = 0;
uint8_t ballRadius = 5;
uint16_t xLimitMin = ballRadius+25;
uint16_t xLimitMax = 240-ballRadius-25;
uint16_t yLimitMin = ballRadius+25;
uint16_t yLimitMax = 320-ballRadius-25;
for(;;) {
xSemaphoreTake( xMutex, portMAX_DELAY );
if (xy.x > 3000 && !(xCoord < xLimitMin))
xCoord -= 5;
if (xy.x < 1000 && !(xCoord > xLimitMax))
xCoord += 5;
if (xy.y > 3000 && !(yCoord < yLimitMin))
yCoord -= 5;
if (xy.y < 1000 && !(yCoord > yLimitMax))
yCoord += 5;
reads++;
BSP_LCD_Clear(LCD_COLOR_WHITE);
BSP_LCD_DrawCircle(xCoord, yCoord, ballRadius);
BSP_LCD_FillCircle(xCoord, yCoord, ballRadius);
xSemaphoreGive(xMutex);
HAL_Delay(20);
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI4_Init();
MX_TIM1_Init();
MX_USART1_UART_Init();
// LCD Things
BSP_LCD_Init();
BSP_LCD_LayerDefaultInit(1, LCD_FRAME_BUFFER);
BSP_LCD_SelectLayer(1);
BSP_LCD_SetBackColor(LCD_COLOR_WHITE); // Vali meelepärane värv
BSP_LCD_Clear(LCD_COLOR_WHITE);
BSP_LCD_SetTextColor(LCD_COLOR_DARKBLUE); // Vali meelepärane värv
MX_FREERTOS_Init();
if ( xMutex == NULL )
{
xMutex = xSemaphoreCreateMutex();
if ( ( xMutex ) != NULL )
xSemaphoreGive( ( xMutex ) );
}
xTaskCreate(vTaskFunction1, "Task 1", 100, NULL, 1, NULL);
xTaskCreate(vTaskFunction2, "Task 2", 100, NULL, 1, NULL);
vTaskStartScheduler();
osKernelStart();
while (1)
{
}
}
Чтение функции джойстика (joystick.c)
#include <stdio.h>
#include <main.h>
#include "gpio.h"
#include "spi.h"
#define READ_SLAVE_OPERATION 0b10000000
#define READ_INCR_SLAVE_OPERATION 0b11000000
#define WRITE_SLAVE_OPERATION 0b00000000
#define CTRL_REG_IN3 0b00000011
#define CTRL_REG_IN4 0b00000100
#define OUT_X_L 0x28
#define OUT_X_H 0x29
#define OUT_Y_L 0x2A
#define OUT_Y_H 0x2B
#define OUT_Z_L 0x2C
#define OUT_Z_H 0x2D
#define JOY_CS_LOW() HAL_GPIO_WritePin(JOY_CS_GPIO_PORT, JOY_CS_PIN, 0)
#define JOY_CS_HIGH() HAL_GPIO_WritePin(JOY_CS_GPIO_PORT, JOY_CS_PIN, 1)
#define JOY_CS_GPIO_PORT GPIOC
#define JOY_CS_PIN GPIO_PIN_13
int16_t Joy_ReadXY(uint8_t reg1){
uint8_t pTxData1[2] = {reg1, 0};
uint8_t pRxData1[2] = {0, 0};
JOY_CS_LOW();
HAL_SPI_TransmitReceive(&hspi4, pTxData1, pRxData1, 2, HAL_MAX_DELAY);
JOY_CS_HIGH();
return pRxData1[0] << 8 | pRxData1[1];
}
запустите strace
или gdb
, чтобы локализовать, где возникает ошибка
@ralfhtp Вы ожидаете, что это будет проблема во время выполнения? Читается для меня как предупреждение/ошибка времени компиляции.
Не обязательно, но вы можете отлаживать проблемы с кодом также с помощью strace и gdb.
Нет, если ошибка компилятора препятствует сборке и запуску.
Компилятор @ralfhtp предотвращает сборку и запуск.
@Yunnosch извините за глупый вопрос, не могли бы вы уточнить, что именно мне делать? Я имею в виду, например, где я должен их добавить?
Если под «ними» вы имеете в виду прототип int16_t Joy_ReadXY(uint8_t reg1);
, я хочу, чтобы вы вставили именно эту единственную строку непосредственно перед строкой с заголовком функции void vTaskFunction1(void *pvParameters)
(за которой следует тело функции {...}
), то есть между этой строкой и предыдущей строкой Joystick_data xy;
Внутри Main.c примерно номер строки 8.
@Yunnosch хорошо, понял. Итак, теперь это дает мне новую ошибку: «Конфликтующие типы для «Joy_ReadXY».
Интересно, не так ли? Я мог бы быть на что-то. Попробуйте #define CTRL_REG_IN3 0x18
и #define CTRL_REG_IN4 0x20
. Вы видите, что это то, что вы подразумеваете под своими двумя определениями, просто в шестнадцатеричном формате, не так ли?
Кстати, почему вы по-разному определяете эти два макроса в двух файлах .c? Какое из двух определений верно? Или есть причина для двух разных значений в зависимости от файла кода?
@Yunnosch 1) Да, я это вижу. 2) Хороший вопрос, кажется, я только что увидел в какой-то таблице другое значение... и забыл их изменить. 0x18/0x20 они оба правильные. Нет причин, для двух разных значений.
Вы пробовали модифицированные определения макросов, которые я предложил? В противном случае я могу ответить на вопрос как есть, потому что ошибка, о которой вы спрашиваете, исправлена моим первым предложением.
Теперь, когда я ответил, пожалуйста, создайте отдельный новый вопрос о новой ошибке, которая возникает после исправления ошибки, описанной в вопросе, как есть.
Здесь, в Main.c, вы вызываете функцию, прежде чем сообщить компилятору о том, какие параметры и какие типы возвращаемых значений она имеет.
localX = Joy_ReadXY(CTRL_REG_IN3);
localY = Joy_ReadXY(CTRL_REG_IN4)
Это запутало компилятор, и он начинает о них «догадываться».
Предполагая, что это функция, возвращающая void, компилятор затем жалуется, что вы ожидаете возвращаемого значения от функции, которая возвращает void
, то есть ничего.
Возвращенный void
следует игнорировать, а не пытаться записать его в переменную. По крайней мере, так думает компилятор...
Чтобы исправить это, вы должны объяснить компилятору, что в другом месте есть функция с именем, параметрами и типом возвращаемого значения. Это делается путем предоставления прототипа
int16_t Joy_ReadXY(uint8_t reg1);
Это нужно сделать перед телом функции, в котором функция extern вызывается впервые. (И вы уже подтвердили в комментариях, что это устраняет описанную проблему в вашем коде.)
Обратите внимание, что для других показанных функций это не требуется, потому что они определены (с головой и телом) до того, как будут вызваны. Аналогично для других функций, прототип которых указан в заголовке, который вы включили ранее.
На самом деле, размещение прототипа вашей функции в заголовке и включение его аналогичным образом было бы лучшим способом решить эту проблему.
Я думаю, что вы путаете компилятор отсутствием прототипа. Пожалуйста, попробуйте добавить
int16_t Joy_ReadXY(uint8_t reg1);
передvoid vTaskFunction1(void *pvParameters) {
. Если это поможет, я создам объясненный ответ.