妈蛋,先插了代码文字要打在里面了,管不了了。昨天开始准备在STM32F411RE上对TLC59401进行软件验证,云上不能调试,于是在本地搭建环境,搭了半天,深感公司对于信息安全的重视程度到了令人发指的地步。
以下为吐槽,闲杂人等可以跳过。
首先因为本地只能上内网,所以把IAR相关的软件和Licence破解之类的工具通过greenetrans传到本地,本地安装了半天。。。
调试要代码吧要库吧,于是把代码打包,准备通过绿传传到本地,突然发现,被检测到是代码就给我rejected了。。。我日。。
怎么办?
SVN?不行,那是管理版本的怎么能用来给我传代码。。
不过机制的我机智地把代码压缩分卷成了好几份,Espace传给同事小伙伴,然后下线,在本地登陆Espace,让小伙伴再传过来。。
真累啊。。。
。。。
终于环境搭好了,二话不说,进主题。
先看main函数如下:
1 /** 2 * @brief Main program 3 * @param None 4 * @retval None 5 */ 6 int main(void) 7 { 8 /* STM32F4xx HAL library initialization: 9 - Configure the Flash prefetch, instruction and Data caches 10 - Configure the Systick to generate an interrupt each 1 msec 11 - Set NVIC Group Priority to 4 12 - Global MSP (MCU Support Package) initialization 13 */ 14 HAL_Init(); 15 16 /* Configure the system clock to 100 MHz */ 17 SystemClock_Config(); 18 19 /*##-1- Enable GPIOA Clock (to be able to program the configuration registers) */ 20 __HAL_RCC_GPIOA_CLK_ENABLE(); 21 22 /*##-2- Configure PA05 IO in output push-pull mode to drive external LED ###*/ 23 GPIO_InitStruct.Pin = GPIO_PIN_5; 24 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出 25 GPIO_InitStruct.Pull = GPIO_NOPULL ; //默认悬空 26 GPIO_InitStruct.Speed = GPIO_SPEED_FAST; //管脚响应速度配置 27 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 28 29 /*##-3- Toggle PA05 IO in an infinite loop #################################*/ 30 unsigned int i=0; 31 while (1) 32 { 33 ((++i)%2==0)?(HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET)):(HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET)); 34 //HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); 35 //HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,1); 36 /* Insert a 100ms delay */ 37 HAL_Delay(100); 38 } 39 }
1 typedef struct 2 { 3 uint32_t Pin; /*!< Specifies the GPIO pins to be configured. 4 This parameter can be any value of @ref GPIO_pins_define */ 5 6 uint32_t Mode; /*!< Specifies the operating mode for the selected pins. 7 This parameter can be a value of @ref GPIO_mode_define */ 8 9 uint32_t Pull; /*!< Specifies the Pull-up or Pull-Down activation for the selected pins. 10 This parameter can be a value of @ref GPIO_pull_define */ 11 12 uint32_t Speed; /*!< Specifies the speed for the selected pins. 13 This parameter can be a value of @ref GPIO_speed_define */ 14 15 uint32_t Alternate; /*!< Peripheral to be connected to the selected pins. 16 This parameter can be a value of @ref GPIO_Alternate_function_selection */ 17 }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等于什么?
1 #define GPIO_PIN_0 ((uint16_t)0x0001U) /* Pin 0 selected */ 2 #define GPIO_PIN_1 ((uint16_t)0x0002U) /* Pin 1 selected */ 3 #define GPIO_PIN_2 ((uint16_t)0x0004U) /* Pin 2 selected */ 4 #define GPIO_PIN_3 ((uint16_t)0x0008U) /* Pin 3 selected */ 5 #define GPIO_PIN_4 ((uint16_t)0x0010U) /* Pin 4 selected */ 6 #define GPIO_PIN_5 ((uint16_t)0x0020U) /* Pin 5 selected */ 7 #define GPIO_PIN_6 ((uint16_t)0x0040U) /* Pin 6 selected */ 8 #define GPIO_PIN_7 ((uint16_t)0x0080U) /* Pin 7 selected */ 9 #define GPIO_PIN_8 ((uint16_t)0x0100U) /* Pin 8 selected */ 10 #define GPIO_PIN_9 ((uint16_t)0x0200U) /* Pin 9 selected */ 11 #define GPIO_PIN_10 ((uint16_t)0x0400U) /* Pin 10 selected */ 12 #define GPIO_PIN_11 ((uint16_t)0x0800U) /* Pin 11 selected */ 13 #define GPIO_PIN_12 ((uint16_t)0x1000U) /* Pin 12 selected */ 14 #define GPIO_PIN_13 ((uint16_t)0x2000U) /* Pin 13 selected */ 15 #define GPIO_PIN_14 ((uint16_t)0x4000U) /* Pin 14 selected */ 16 #define GPIO_PIN_15 ((uint16_t)0x8000U) /* Pin 15 selected */ 17 #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口电平。
1 void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState) 2 { 3 /* Check the parameters */ 4 assert_param(IS_GPIO_PIN(GPIO_Pin)); 5 assert_param(IS_GPIO_PIN_ACTION(PinState)); 6 7 if(PinState != GPIO_PIN_RESET) 8 { 9 GPIOx->BSRR = GPIO_Pin; 10 } 11 else 12 { 13 GPIOx->BSRR = (uint32_t)GPIO_Pin << 16U; 14 } 15 }
看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更新。
也希望新人们通过看我这个笔记,能够更加清楚地了解单片机的工作原理。
:)