STM32串口通讯
目录
一、基于寄存器与基于固件库的stm32 LED流水灯例子的编程方式的差异
两个使用的角度不同:
固件库的特点就是简单、易于理解、资料多,等有一定的基础再用寄存器。
寄存器更贴近底层,对外设的工作原理和运行机理会有更深的理解。
二、STM32的USART窗口通讯程序
用usb线把stm32开发板和电脑相连接,stm32端连接的 ‘usb转串口’这个接口,再打开stm32开关
连接过后打开CH341SER.EXE,点击安装
在野火资料包里下载野火串口调试助手,位置如下:
下载完成后解压打开如下软件:
此时显示设置串行口调试设置波特率为115200,1位停止位,无校验位如下:
串口通信的验证,打开官方资料库中的文件:
打开keil5,需要修改具体程序代码,修改后的源文件代码如下:
(1)修改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++;
}
(2)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文件,然后烧录程序到STM32里去
将电脑与单片机通过ST-LINK线连接起来
在keil里进行设置,如下选择ST-Link Debugger:
点击settings:
最后点击编译,下载烧录在野火串口调试助手点击“打开串口”即为显示stm32正在向上机位发送消息:
三、C程序代码各种类型变量的地址空间
打开ubantu,编写一个.c文件:
#include <stdio.h>
#include <stdlib.h>
int k1 = 1;
int k2;
static int k3 = 2;
static int k4;
int main( )
{ static int m1=2, m2;
int i = 1;
char *p;
char str[10] = "hello";
char *var1 = "123456";
char *var2 = "abcdef";
int *p1=malloc(4);
int *p2=malloc(4);
free(p1);
free(p2);
printf("栈区-变量地址\n");
printf(" i:%p\n", &i);
printf(" p:%p\n", &p);
printf(" str:%p\n", str);
printf("\n堆区-动态申请地址\n");
printf(" %p\n", p1);
printf(" %p\n", p2);
printf("\n.bss段\n");
printf("全局外部无初值 k2:%p\n", &k2);
printf("静态外部无初值 k4:%p\n", &k4);
printf("静态内部无初值 m2:%p\n", &m2);
printf("\n.data段\n");
printf("全局外部有初值 k1:%p\n", &k1);
printf("静态外部有初值 k3:%p\n", &k3);
printf("静态内部有初值 m1:%p\n", &m1);
printf("\n常量区\n");
printf("文字常量地址 :%p\n",var1);
printf("文字常量地址 :%p\n",var2);
printf("\n代码区\n");
printf("程序区地址 :%p\n",&main);
return 0;
}
编译后:
在C\C++中,通常可以把内存理解为4个分区:栈、堆、全局/静态存储区和常量存储区。
1.内存栈区: 存放局部变量名;
2. 内存堆区: 存放new或者malloc出来的对象;
3. 常数区: 存放局部变量或者全局变量的值;
4. 静态区: 用于存放全局变量或者静态变量;
可看出,栈的地址的向下增长;堆的地址向上增长;静态变量的地址向下增长;全局常量的地址向上增长;函数的地址向上增长。
四、stm32的堆、栈、全局变量的分配地址
使用之前野火的串口通信模板,把main.c改为如下:
#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按钮,就可以看到如下结果:
part1、2、3变量为局部变量,它们储存到了栈中,地址依次减小。
global1、2、3为全局变量,它们储存到了静态区,地址依次增加。
改为下列函数:
#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)
{
}
}
同理得到:
静态变量st1、2、3储存到了静态区,地址依次增加。
指针p1、2、3指针储存到了堆中,地址依次增加。