stm32系统 的C语法一开始难度大,采用C语言模拟,能快速上手。
简单版本
//run C @ https://www.jyshare.com/compile/11/
#include <stdio.h>
// 模拟GPIO寄存器结构
typedef struct {
unsigned int pinState : 1; // 仅模拟单个引脚的状态,0表示低电平,1表示高电平
} SimpleGPIO_TypeDef;
// 定义一个SimpleGPIO_TypeDef类型的变量,并将其地址强制转换为SimpleGPIO_TypeDef*类型
SimpleGPIO_TypeDef simulatedGPIO = {0};
//或 int simulatedGPIO = 1;//随意数字均可
#define SIMULATED_GPIO_BASE ((SimpleGPIO_TypeDef*)&simulatedGPIO)
// 初始化结构体
typedef struct {
unsigned int pinNumber; // 配置的引脚编号,仅为教学目的模拟
unsigned int initialState; // 初始状态,0或1
} SimpleGPIO_InitTypeDef;
// 模拟GPIO初始化函数
void simpleGPIO_Init(SimpleGPIO_TypeDef* GPIOx, SimpleGPIO_InitTypeDef* initStruct) {
if (initStruct->pinNumber == 2) { // 假设我们只模拟Pin2
GPIOx->pinState = initStruct->initialState; // 设置初始状态
printf("GPIO Pin2 initialized to state %d at address %p.\n",
initStruct->initialState, (void*)SIMULATED_GPIO_BASE);
} else {
printf("Invalid pin number. Simulation supports only Pin2.\n");
}
}
int main() {
SimpleGPIO_InitTypeDef GPIO_Config = {2, 1}; // 配置Pin2,初始状态为高电平
// 使用模拟的基地址初始化模拟GPIO
simpleGPIO_Init(SIMULATED_GPIO_BASE, &GPIO_Config);
return 0;
}
解释 &simulatedGPIO
定义了一个变量simulatedGPIO,取了其地址,模拟GPIOA的地址
SimpleGPIO_TypeDef simulatedGPIO = {0};
//或 int simulatedGPIO = 1;//随意数字均可
#define SIMULATED_GPIO_BASE ((SimpleGPIO_TypeDef*)&simulatedGPIO)
进阶版本
进阶版本,内容更多,更接近了真实的赋值,地址采用了(GPIO_TypeDef *) 0的方式,这个方式不好理解可以略过,理解以上
&simulatedGPIO即可。
#include <stdio.h>
#include <stdint.h>
// 模拟GPIO结构体
typedef struct {
uint32_t GPIO_Pin;
uint32_t GPIO_Mode;
uint32_t GPIO_Speed;
uint32_t GPIO_OType;
uint32_t GPIO_PuPd;
} GPIO_InitTypeDef;
// 模拟GPIO寄存器结构体
typedef struct {
uint32_t MODER;
uint32_t OTYPER;
uint32_t OSPEEDR;
uint32_t PUPDR;
uint32_t IDR;
uint32_t ODR;
// 其他寄存器可以按需添加
} GPIO_TypeDef;
// 模拟GPIO基地址
int PortA=0x12;
int PortC=0x67;//这里没用上,地址直接用0代替
#define GPIOA ((GPIO_TypeDef *) &PortA)
#define GPIOC ((GPIO_TypeDef *) 0) //这里也可以采用上句,更接近stm32真实地址
// 模拟GPIO引脚
#define GPIO_Pin_2 ((uint16_t)0x0004) // PC2
// 模拟GPIO初始化函数
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) {
// 模拟初始化过程
printf("Initializing GPIO pin %d with mode %d, speed %d, output type %d, pull-up/pull-down %d\n",
GPIO_InitStruct->GPIO_Pin, GPIO_InitStruct->GPIO_Mode, GPIO_InitStruct->GPIO_Speed,
GPIO_InitStruct->GPIO_OType, GPIO_InitStruct->GPIO_PuPd);
// 模拟设置寄存器
GPIOx->MODER &= ~(3 << (2 * 2)); // 清除PC2的模式位
GPIOx->MODER |= (GPIO_InitStruct->GPIO_Mode << (2 * 2)); // 设置PC2的模式位
GPIOx->OSPEEDR &= ~(3 << (2 * 2)); // 清除PC2的速度位
GPIOx->OSPEEDR |= (GPIO_InitStruct->GPIO_Speed << (2 * 2)); // 设置PC2的速度位
GPIOx->OTYPER &= ~(1 << 2); // 清除PC2的输出类型位
GPIOx->OTYPER |= (GPIO_InitStruct->GPIO_OType << 2); // 设置PC2的输出类型位
GPIOx->PUPDR &= ~(3 << (2 * 2)); // 清除PC2的上拉/下拉位
GPIOx->PUPDR |= (GPIO_InitStruct->GPIO_PuPd << (2 * 2)); // 设置PC2的上拉/下拉位
}
int main(void) {
// 初始化GPIO结构体
GPIO_InitTypeDef GPIO_PC2_InitStruct;
GPIO_PC2_InitStruct.GPIO_Pin = GPIO_Pin_2;
GPIO_PC2_InitStruct.GPIO_Mode = 1; // 模拟输出模式
GPIO_PC2_InitStruct.GPIO_Speed = 0; // 模拟低速
GPIO_PC2_InitStruct.GPIO_OType = 0; // 模拟推挽输出
GPIO_PC2_InitStruct.GPIO_PuPd = 0; // 模拟无上拉/下拉
// 初始化GPIOC的PC2引脚
GPIO_Init(GPIOC, &GPIO_PC2_InitStruct);
// 主循环
while (1) {
// 模拟主循环
printf("Main loop\n");
break; // 为了简单起见,只执行一次
}
return 0;
}
1理解define GPIOC ((GPIO_TypeDef *) 0)
在C语言中,`(GPIO_TypeDef *) 0`是一个强制类型转换表达式,其中`0`表示一个地址。具体来说:
- `0`:这是一个整数常量,表示内存地址`0`。在计算机系统中,地址`0`通常是一个无效的地址,因为它位于未映射的内存区域。然而,在纯C语言模拟环境中,我们使用`0`来代替实际的内存地址,以避免实际硬件的依赖。
- `(GPIO_TypeDef *)`:这是一个强制类型转换操作符,用于将整数`0`转换为指向`GPIO_TypeDef`类型的指针。这意味着我们假装地址`0`是一个指向`GPIO_TypeDef`结构体的指针。
在实际的STM32微控制器中,每个GPIO端口都有一个基地址,例如GPIOC的基地址可能是`0x40020800`。但在纯C语言模拟环境中,我们不需要实际的内存地址,因此使用`0`来代替。
总结来说,`(GPIO_TypeDef *) 0`中的`0`是一个地址,表示内存地址`0`,通过强制类型转换将其视为指向`GPIO_TypeDef`类型的指针。在纯C语言模拟环境中,这种做法允许我们编写和测试GPIO初始化代码,而不依赖实际硬件。
2 理解#define GPIO_Pin_2 ((uint16_t)0x0004)
这个宏定义的作用是将GPIO_Pin_2
定义为一个16位无符号整数,其值为0x0004
。具体解释如下:
-
GPIO_Pin_2
:这是一个宏名称,代表GPIO端口C的第2号引脚。 -
((uint16_t)0x0004)
:这是一个强制类型转换表达式。它将十六进制数0x0004
转换为16位无符号整数。
在STM32微控制器中,每个GPIO引脚都有一个对应的位掩码,用于标识该引脚。例如,GPIOC的第2号引脚的位掩码是0x0004
,表示该引脚在寄存器中的位置。