0.前言
我们的比赛采用stm32开发,因此这两天我学习了stm32的基本使用,并自己写了一些程序来测试。 由于本人之前对stm32毫无熟悉,只是作为计算机专业的学生,从数字逻辑、计算机组成原理等课程中学习到了一些硬件知识,因此以下的一些介绍可能不够严谨,还望各位保包涵。
废话不多说,开始正文
1.项目创建
当你下好了cubemx,并且安装好了对应芯片的固件包后,我们点击File-New Project,弹出如下框,输入我们使用的芯片(本人使用stm32F103RCT6,因此搜索stm32F103RC,在选择Tx) 接下来到达如下的配置界面,便可以开始配置了
2.LED、按键的配置
首先,通过查阅资料,我总结出了要配置的外设的一些基本参数 (本人使用的是正点原子的mini stm32开发板,芯片为stm32F103RCT6) 本次实验暂且只用到了DS0,DS1,KEY0,KEY1,串口1 首先是DS0的配置,端口是PA8,因此我们找出PA8,并点击为GPIO_Output 配置尚未结束,我们需要再进行一些额外的设置 第一行是初始的电平值,这里暂未修改;第二行是输出模式,也不用改;第三行是选择上下拉,我们选择上拉;第四行是输出速率,选择高速; DS1的配置同理,这里不再复述。
接下来是按键的配置,由于按键打算以外设中断的方式来实现,因此这里的设置如下: 与之前配置LED的方式类似,但最后要改成GPIO_EXTI5 进一步的配置不需改变 之后,由于是外设中断,需要对NVIC进行设置。 KEY1的配置类似,不再复述。
3.串口配置
串口使用到了PA9和PA10,其中PA9是推挽输出,PA10是服用输出 其中,PA9要点击USART1_TX,PA10要点成USART1_RX 在之后,对串口进行一些配置,如下
4.时钟配置
时钟配置这块,也可以在配置引脚前先配好。 首先,选择高速时钟为Crystal/Ceramic Resonator(晶体/陶瓷谐振器),低速时钟用不到,不配置 之后,配置时钟树如下
5.导出代码
在之后,点击Project Manager,在Project栏进行配置,重点的地方已勾选出。 因为我们是keil5,因此IDE选择MDK-ARM V5 之后在Code Generator栏进行配置如下: 之后,点击GENERATE CODE便可以导出代码 如果没有Open Project的话,可能是没有下载某些包,具体得可以检查一下前期配置是否有疏漏,一般这种情况下在生成前会给出提示要下载某些东西,下载就好。
5.逻辑编写
目前我打算用串口实现下位机和上位机的全双工通信,即:
- 下位机通过按键向上位机串口发送一些数据
- 上位机通过串口向下位机发送数据以点亮LED
5.1重写printf函数用于串口发送
重写printf函数是为了方便串口的发送,不然串口发送的函数还是很长的,并且要规定长度,比较麻烦。 重写过程如下:
-
找到usart.h,加入头文件 stdio.h -
在usart.c中,添加如下代码 #ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int _io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,0xFFFF);
return ch;
}
这段代码的作用是重写了printf的底层函数(例如fputc),以便对每个字节进行发送 之后引入了usart.h的文件便可以直接用printf来实现串口发送了
5.1下位机发送
由于我们是按下按键进行发送,因此我们要在按键中断的处理函数中编写发送逻辑。 其中,所谓的“处理函数”是回调函数HAL_GPIO_EXTI_Callback,我们需要重写这个函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
HAL_Delay(10);
switch(GPIO_Pin){
case GPIO_PIN_5:
printf("KEY0 has pressed!\r\n");
break;
case GPIO_PIN_15:
printf("KEY1 has pressed!\r\n");
break;
default:
break;
}
}
5.3下位机接收
接收的逻辑较为复杂,大致的思想是一个字节一个字节的接收,当连续检测到终止符"\r\n"的时候表示发送完毕 此后进入逻辑部分。 由于stm32的C语言中变量貌似不能在函数体中定义,因此需要提前定义好。
#define RCLENGTH 255
uint8_t Buffer[RCLENGTH];
uint8_t byte;
uint8_t length=0;
void LED_set(){
if(length<=2) return;
if((Buffer[length-2]&0x1)==1){
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_8);
}
else{
HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_2);
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart){
if(1){
Buffer[length++]=byte;
if((length>=2) && (Buffer[length-1]==0x0A) && (Buffer[length-2]==0x0D)){
LED_set();
length=0;
memset(Buffer,0,sizeof(Buffer));
}
HAL_UART_Receive_IT(&huart1,(uint8_t*)&byte,1);
}
}
当然,在main函数中需要添加如下语句,否则就接收不到了
6.验收
编译,显示无报错 打开flymcu,选择指定hex文件进行下载 下板后,点击按键,发现有反应 上位机发送数据,也可以改变灯的亮灭 这块不再展示
7.总结
总结一下大致流程
- 使用cubemx配置GPIO、USART等,并配置中断优先级
- 导出代码后,在keil5中编写处理逻辑
- 使用flymcu下板,并用XCOM进行串口调试(你甚至可以自己写一个)
最后,感谢你的浏览!
|