STM32F411RE简单的GPIO控制与调试

妈蛋,先插了代码文字要打在里面了,管不了了。昨天开始准备在STM32F411RE上对TLC59401进行软件验证,云上不能调试,于是在本地搭建环境,搭了半天,深感公司对于信息安全的重视程度到了令人发指的地步。

以下为吐槽,闲杂人等可以跳过。

首先因为本地只能上内网,所以把IAR相关的软件和Licence破解之类的工具通过greenetrans传到本地,本地安装了半天。。。

调试要代码吧要库吧,于是把代码打包,准备通过绿传传到本地,突然发现,被检测到是代码就给我rejected了。。。

怎么办?

SVN?不行,那是管理版本的怎么能用来给我传代码。。

不过机制的我机智地把代码压缩分卷成了好几份,Espace传给同事小伙伴,然后下线,在本地登陆Espace,让小伙伴再传过来。。

真累啊。。

终于环境搭好了,二话不说,进主题。

先看main函数如下:
/**
* @brief Main program
* @param None
* @retval None
*/
int main(void)
{
/* STM32F4xx HAL library initialization:
- Configure the Flash prefetch, instruction and Data caches
- Configure the Systick to generate an interrupt each 1 msec
- Set NVIC Group Priority to 4
- Global MSP (MCU Support Package) initialization
*/
HAL_Init();

/* Configure the system clock to 100 MHz */
SystemClock_Config();

/*##-1- Enable GPIOA Clock (to be able to program the configuration registers) */
__HAL_RCC_GPIOA_CLK_ENABLE();

/*##-2- Configure PA05 IO in output push-pull mode to drive external LED ###*/
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_InitStruct.Pull = GPIO_NOPULL ; //默认悬空
GPIO_InitStruct.Speed = GPIO_SPEED_FAST; //管脚响应速度配置
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/*##-3- Toggle PA05 IO in an infinite loop #################################*/
unsigned int i=0;
while (1)
{
((++i)%2==0)?(HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET)):(HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET));
//HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
//HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,1);
/* Insert a 100ms delay */
HAL_Delay(100);
}
}

typedef struct
{
uint32_t Pin; /*!< Specifies the GPIO pins to be configured.
This parameter can be any value of @ref GPIO_pins_define */

uint32_t Mode; /*!< Specifies the operating mode for the selected pins.
This parameter can be a value of @ref GPIO_mode_define */

uint32_t Pull; /*!< Specifies the Pull-up or Pull-Down activation for the selected pins.
This parameter can be a value of @ref GPIO_pull_define */

uint32_t Speed; /*!< Specifies the speed for the selected pins.
This parameter can be a value of @ref GPIO_speed_define */

uint32_t Alternate; /*!< Peripheral to be connected to the selected pins.
This parameter can be a value of @ref GPIO_Alternate_function_selection */
}GPIO_InitTypeDef;

来看GPIO_Initstruct的定义,

里面有Pin—管脚号;

Mode-输入模式或者输出模式,其中输出又分为推挽输出和开漏输出,不了解的同学可以去查阅相关资料,简单地说如果你想要电平转换速度快的话,那么就选push-pull,但是缺点是功耗相对会大些。

如果你想要功耗低,且同时具有“线与”的功能,那么就用open-drain的模式;

Pull—默认时的状态,上拉下拉还是浮空,即初始电平;

Speed—设置IO口响应速度;

Alternate—这个不清楚,没用过,似乎也没啥用。 

main函数的init配置里有GPIO_InitStruct.Pin = GPIO_PIN_5;

我们来看GOIO_PIN_5等于什么?

#define GPIO_PIN_0 ((uint16_t)0x0001U) /* Pin 0 selected */
#define GPIO_PIN_1 ((uint16_t)0x0002U) /* Pin 1 selected */
#define GPIO_PIN_2 ((uint16_t)0x0004U) /* Pin 2 selected */
#define GPIO_PIN_3 ((uint16_t)0x0008U) /* Pin 3 selected */
#define GPIO_PIN_4 ((uint16_t)0x0010U) /* Pin 4 selected */
#define GPIO_PIN_5 ((uint16_t)0x0020U) /* Pin 5 selected */
#define GPIO_PIN_6 ((uint16_t)0x0040U) /* Pin 6 selected */
#define GPIO_PIN_7 ((uint16_t)0x0080U) /* Pin 7 selected */
#define GPIO_PIN_8 ((uint16_t)0x0100U) /* Pin 8 selected */
#define GPIO_PIN_9 ((uint16_t)0x0200U) /* Pin 9 selected */
#define GPIO_PIN_10 ((uint16_t)0x0400U) /* Pin 10 selected */
#define GPIO_PIN_11 ((uint16_t)0x0800U) /* Pin 11 selected */
#define GPIO_PIN_12 ((uint16_t)0x1000U) /* Pin 12 selected */
#define GPIO_PIN_13 ((uint16_t)0x2000U) /* Pin 13 selected */
#define GPIO_PIN_14 ((uint16_t)0x4000U) /* Pin 14 selected */
#define GPIO_PIN_15 ((uint16_t)0x8000U) /* Pin 15 selected */
#define GPIO_PIN_All ((uint16_t)0xFFFFU) /* All pins selected */

可以看到GPIO_PIN_5十六进制表示就是0x0020U,转换为二进制即0000 0000 0010 0000 对应的就是第六个管脚PIN5。

同样地,结构体里别的变量的值的设置其实就是按datasheet里寄存器的配置把十六位二进制转成四位十六进制,然后通过define定义为各种名称,应该很容易理解。

 1 ((++i)%2==0)?(HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET)):(HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET)); 

while里的这句是要实现什么呢?

是的,就是根据i的奇偶来交替拉高拉低IO口电平。

void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
{
/* Check the parameters */
assert_param(IS_GPIO_PIN(GPIO_Pin));
assert_param(IS_GPIO_PIN_ACTION(PinState));

if(PinState != GPIO_PIN_RESET)
{
GPIOx->BSRR = GPIO_Pin;
}
else
{
GPIOx->BSRR = (uint32_t)GPIO_Pin << 16U;
}
}

看HAL_GPIO_WritePin,GPIOx和GPIO_Pin就不提了,主要是PinState,当它非零时(=。=GPIO_PIN_RESET肯定是0啦我用膝盖想一下就知道)给GPIOx->BSRR写入GPIO_Pin,即把相对应的管脚为1的电平拉高;

如果它为零时,就GPIOx->BSRR=0000 0000 0000 0000啦,所有管脚拉低,即复位。

很简单的内容,要实现的也能简单,我这里GPIOA_Pin5连着LED二极管,所以烧写后效果就是100ms亮、100ms灭交替进行下去。

一年多没用过MCU了,算是新的开始吧。以后解决了什么问题也会在blog更新。

也希望新人们通过看我这个笔记,能够更加清楚地了解单片机的工作原理。

永不止步步 发表于01-03 10:22 浏览65535次
分享到:

已有0条评论

暂时还没有回复哟,快来抢沙发吧

添加一条新评论

只有登录用户才能评论,请先登录注册哦!

话题作者

永不止步步
金币:67410个|学分:308117个
立即注册
畅学电子网,带你进入电子开发学习世界
专业电子工程技术学习交流社区,加入畅学一起充电加油吧!

x

畅学电子网订阅号