#define оператор для адреса памяти - PullRequest
1 голос
/ 08 января 2020

Что делает этот оператор #define? Он используется для определения адреса памяти. Но я не понимаю (uint32_t *) часть

#define GPxDAT (uint32_t *) 0x6FC0 

Ответы [ 2 ]

3 голосов
/ 08 января 2020

Обычно используется для доступа к аппаратным регистрам, отображаемым в адресном пространстве, или к некоторым конкретным адресам памяти.

Аппаратные регистры должны быть определены как volatile, поскольку регистры могут изменяться без какой-либо активности программы (так как они изменяются аппаратным обеспечением).

#define GPIOREGA ((volatile uint32_t *) 0x6FC0) 

затем вы можете назначить или прочитать эту область памяти (*GPIOREGA = something; something = *GPIOREGA)

Иногда таким способом используются гораздо более сложные структуры данных (пример из заголовков STM32) )

#define __IO volatile

typedef struct
{
  __IO uint32_t MODER;    /*!< GPIO port mode register,               Address offset: 0x00      */
  __IO uint32_t OTYPER;   /*!< GPIO port output type register,        Address offset: 0x04      */
  __IO uint32_t OSPEEDR;  /*!< GPIO port output speed register,       Address offset: 0x08      */
  __IO uint32_t PUPDR;    /*!< GPIO port pull-up/pull-down register,  Address offset: 0x0C      */
  __IO uint32_t IDR;      /*!< GPIO port input data register,         Address offset: 0x10      */
  __IO uint32_t ODR;      /*!< GPIO port output data register,        Address offset: 0x14      */
  __IO uint32_t BSRR;     /*!< GPIO port bit set/reset register,      Address offset: 0x18      */
  __IO uint32_t LCKR;     /*!< GPIO port configuration lock register, Address offset: 0x1C      */
  __IO uint32_t AFR[2];   /*!< GPIO alternate function registers,     Address offset: 0x20-0x24 */
} GPIO_TypeDef;

#define PERIPH_BASE           0x40000000U /*!< Peripheral base address in the alias region                                */

#define AHB1PERIPH_BASE       (PERIPH_BASE + 0x00020000U)
#define GPIOA_BASE            (AHB1PERIPH_BASE + 0x0000U)

#define GPIOA               ((GPIO_TypeDef *) GPIOA_BASE)

И вы можете использовать его как любой обычный указатель

GPIOA -> MODER |= (1 << 15);
0 голосов
/ 10 января 2020

(uint32_t *) часть - это то, что называется приведением , оно преобразует целое число 0x6FC0 в указатель (адрес) в unsigned целое число, 32 бита широкий (это то, что представляет тип uint32_t.) В основном преобразование типа в указатель на целое число без знака. На мой взгляд, выражение не совсем безопасно. Хотя оператор приведения имеет высокий приоритет, он должен быть записан как:

#define  GPxDAT ((uint32_t *) 0x6FC0)

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

При записи такого рода определений вы можете получить доступ к GPxDAT[0] как 32-битному целому без знака по адресу 0x6fc0, GPxDAT[1] как следующему 32-битному адресу (выше предыдущего), все они основаны на адрес представлен номером.

...