这里写自定义目录标题
STM32串口通信
一、基于寄存器与基于固件库编写的差异
固件库编写方式,特点是简单易于理解,资料多。新手适合用这种方式入门。
寄存器的可移植性强,更贴近底层,要求对外设的工作原理和运行机理有更深的理解。
二. STM32的USART窗口通讯
连接tm32f103指南者
开发板上有黄色的跳帽,是相当于导线的作用,此处要求BOOT0和BOOT1接地,RXD接A9,TXD接A10,开发板买来默认就是这样接的,所以不需要改动。
安装驱动
打开资源里面的CH341SER.EXE,点击安装,显示安装成功即可。
打开串口下载助手mcuisp
按如下方式配置:①搜索串口,设置波特率 115200(尽量不要设置的太高) ,②选择要下载的 HEX 文件、③校验、编程后执行、④DTR 低电平复位,RTS 高电平进入 bootloader、⑤开始编程。(前4步一定要调试正确,否则可能连接不上)
代码要求
(1)设置波特率为115200,1位停止位,无校验位。
(2)STM32系统给上位机(win10)连续发送“hello windows!”,上位机接收程序可以使用“串口调试助手“,也可自己编程。
(3)当上位机给stm32发送“Stop,stm32”后,stm32停止发送。
解压后打开第21个串口通信文件中的USART1接发中的工程文件
然后把其中stm32f10x_it.c文件的串口中断服务函数部分改为如下:
int i=0;
uint8_t ucTemp[50];
void DEBUG_USART_IRQHandler(void)
{
if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET)
{
ucTemp[i] = USART_ReceiveData(USART1);
}
if(ucTemp[i] == '!')
{
if(ucTemp[i-1] == '2'&&ucTemp[i-2] == '3'&&ucTemp[i-3] == 'm'&&ucTemp[i-4] == 't'&&ucTemp[i-5] == 's'&&ucTemp[i-6] == ' ')
if(ucTemp[i-7] == 'p'&&ucTemp[i-8] == 'o'&&ucTemp[i-9] == 't'&&ucTemp[i-10] == 's')
{
printf("ÊÕµ½£¡");
while(1);
}
}
i++;
}
然后把main.c函数改为
#include "stm32f10x.h"
#include "bsp_usart.h"
void delay(uint32_t count)
{
while(count--);
}
int main(void)
{
USART_Config();
while(1)
{
printf("hello windows 10!\n");
delay(5000000);
}
}
然后就可以编译生成hex文件了,按照上面的方式把hex文件烧录到stm32中,然后打开最开始下载的串口调试助手,点击打开串口,即可以看到stm32发给电脑的信息、
最终效果如下
三. 重温C语言程序里全局变 量、局部变量、堆、栈等概念,并在ubuntu系统中编程,输出信息进行验证。
在vscode中输入代码
定义并输出4个全局变量的地址
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char g_buf[16];
char g_buf2[16];
char g_buf3[16];
char g_buf4[16];
int main()
{
printf("g_buf: 0x%x\n", g_buf);
printf("g_buf2: 0x%x\n", g_buf2);
printf("g_buf3: 0x%x\n", g_buf3);
printf("g_buf4: 0x%x\n", g_buf4);
return 0;
}
发现地址在全局区域里,依次递增
定义并输出3个局部变量的地址
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char l_buf[16];
char l_buf2[16];
char l_buf3[16];
printf("l_buf: 0x%x\n", l_buf);
printf("l_buf2: 0x%x\n", l_buf2);
printf("l_buf3: 0x%x\n", l_buf3);
}
地址依次递增
四、stm32的堆、栈、全局变量的分配地址
串口通信模板,把main.c(分别在stm32中定义了全局变量和局部变量,并把它们的地址返回给windows)改为如下:
#include "stm32f10x.h"
#include "bsp_usart.h"
char global1[16];
char global2[16];
char global3[16];
int main(void)
{
char part1[16];
char part2[16];
char part3[16];
USART_Config();
printf("part1: 0x%p\n", part1);
printf("part2: 0x%p\n", part2);
printf("part3: 0x%p\n", part3);
printf("global1: 0x%p\n", global1);
printf("global2: 0x%p\n", global2);
printf("global3: 0x%p\n", global3);
while(1)
{
}
}
生成hex文件后,烧录到stm32中,打开串口调试助手,点击打开串口,后点击stm32上的reset按钮,
前3个part变量为局部变量,它们储存到了栈中,地址依次减小。
后三个global为全局变量,它们储存到了静态区,地址依次增加。
定义了静态变量和指针
#include "stm32f10x.h"
#include "bsp_usart.h"
#include <stdlib.h>
int main(void)
{
static char st1[16];
static char st2[16];
static char st3[16];
char *p1;
char *p2;
char *p3;
USART_Config();
printf("st1: 0x%p\n", st1);
printf("st2: 0x%p\n", st2);
printf("st3: 0x%p\n", st3);
p1 = (char *)malloc(sizeof(char) * 16);
p2 = (char *)malloc(sizeof(char) * 16);
p3 = (char *)malloc(sizeof(char) * 16);
printf("p1: 0x%p\n", p1);
printf("p2: 0x%p\n", p2);
printf("p3: 0x%p\n", p3);
while(1)
{
}
}
前三个静态变量储存到了静态区,地址依次增加。
后三个指针储存到了堆中,地址依次增加。
结合两次结果看(针对于测试的3个区域),可以大概看出栈在顶层(地址最大),然后依次是堆,静态区。对比以下地址分配图,大致符合。
五.总结
通过这次的作业,我对stm32有了浓厚的兴趣。接下来也要努力学习。