Это правильный способ доступа к функции?

В настоящее время я использую «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];
}

Я думаю, что вы путаете компилятор отсутствием прототипа. Пожалуйста, попробуйте добавить int16_t Joy_ReadXY(uint8_t reg1); перед void vTaskFunction1(void *pvParameters) {. Если это поможет, я создам объясненный ответ.

Yunnosch 14.12.2020 13:21

запустите strace или gdb, чтобы локализовать, где возникает ошибка

ralf htp 14.12.2020 13:21

@ralfhtp Вы ожидаете, что это будет проблема во время выполнения? Читается для меня как предупреждение/ошибка времени компиляции.

Yunnosch 14.12.2020 13:22

Не обязательно, но вы можете отлаживать проблемы с кодом также с помощью strace и gdb.

ralf htp 14.12.2020 13:23

Нет, если ошибка компилятора препятствует сборке и запуску.

Yunnosch 14.12.2020 13:23

Компилятор @ralfhtp предотвращает сборку и запуск.

Vlad Paskevits 14.12.2020 14:03

@Yunnosch извините за глупый вопрос, не могли бы вы уточнить, что именно мне делать? Я имею в виду, например, где я должен их добавить?

Vlad Paskevits 14.12.2020 14:05

Если под «ними» вы имеете в виду прототип int16_t Joy_ReadXY(uint8_t reg1);, я хочу, чтобы вы вставили именно эту единственную строку непосредственно перед строкой с заголовком функции void vTaskFunction1(void *pvParameters) (за которой следует тело функции {...}), то есть между этой строкой и предыдущей строкой Joystick_data xy; Внутри Main.c примерно номер строки 8.

Yunnosch 14.12.2020 14:33

@Yunnosch хорошо, понял. Итак, теперь это дает мне новую ошибку: «Конфликтующие типы для «Joy_ReadXY».

Vlad Paskevits 14.12.2020 14:40

Интересно, не так ли? Я мог бы быть на что-то. Попробуйте #define CTRL_REG_IN3 0x18 и #define CTRL_REG_IN4 0x20. Вы видите, что это то, что вы подразумеваете под своими двумя определениями, просто в шестнадцатеричном формате, не так ли?

Yunnosch 14.12.2020 14:50

Кстати, почему вы по-разному определяете эти два макроса в двух файлах .c? Какое из двух определений верно? Или есть причина для двух разных значений в зависимости от файла кода?

Yunnosch 14.12.2020 14:52

@Yunnosch 1) Да, я это вижу. 2) Хороший вопрос, кажется, я только что увидел в какой-то таблице другое значение... и забыл их изменить. 0x18/0x20 они оба правильные. Нет причин, для двух разных значений.

Vlad Paskevits 14.12.2020 15:00

Вы пробовали модифицированные определения макросов, которые я предложил? В противном случае я могу ответить на вопрос как есть, потому что ошибка, о которой вы спрашиваете, исправлена ​​моим первым предложением.

Yunnosch 14.12.2020 15:02

Теперь, когда я ответил, пожалуйста, создайте отдельный новый вопрос о новой ошибке, которая возникает после исправления ошибки, описанной в вопросе, как есть.

Yunnosch 14.12.2020 15:30
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
14
69
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Здесь, в 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 вызывается впервые. (И вы уже подтвердили в комментариях, что это устраняет описанную проблему в вашем коде.)

Обратите внимание, что для других показанных функций это не требуется, потому что они определены (с головой и телом) до того, как будут вызваны. Аналогично для других функций, прототип которых указан в заголовке, который вы включили ранее.

На самом деле, размещение прототипа вашей функции в заголовке и включение его аналогичным образом было бы лучшим способом решить эту проблему.

Другие вопросы по теме