STM32串口通信

一、想一想

基于寄存器与基于固件库的stm32 LED流水灯例子的编程方式有什么差异?

答:使用固件库的特点是简单,易于理解,资料多。在没有CortexM系统内核开发基础的情况下更易于操作。寄存器更贴近底层,学习寄存器编程,对外设的工作原理和运行机理会有更加深入的理解。
扩展:
STM32标准外设库之前的版本也称固件函数库或简称固件库,是一个固件函数包,它由程序、数据结构和宏组成,包括了微控制器所有外设的性能特征。
寄存器是中央处理器内的组成部分。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和地址。
在中央处理器的控制部件中,包含的寄存器有指令寄存器(IR)和程序计数器(PC)。在中央处理器的算术及逻辑部件中,寄存器有累加器(ACC)。

二、STM32的USART窗口通讯

要求:

1)设置波特率为115200,1位停止位,无校验位。

2)STM32系统给上位机(win10)连续发送“hello windows!”,上位机接收程序可以使用“串口调试助手“,也可自己编程。

3)当上位机给stm32发送“Stop,stm32”后,stm32停止发送。

烧录程序

stm32开发板与电脑连接

连接如图
在这里插入图片描述

打开工程文件并做修改,生成hex文件

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);
	}	
}

在这里插入图片描述
3)编译生成hex文件
在这里插入图片描述

打开341.EXE,点击安装;打开fire tools.exe

在这里插入图片描述
在这里插入图片描述

点击“load”

在这里插入图片描述

结果呈现

打开串口
在这里插入图片描述

三、C语言程序里全局变量、局部变量、堆、栈

概念

全局变量:全局变量是可以在整个程序中访问的变量,它的定义是在函数外的。
局部变量:定义在函数内部的变量,只能在其被声明的函数内部访问。
堆:一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。
栈:由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

在Ubantu中的验证

新建文件c.c,并将下面代码复制到c.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
void before()
{
 
}
 
char g_buf[16];
char g_buf2[16];
char g_buf3[16];
char g_buf4[16];
char g_i_buf[]="123";
char g_i_buf2[]="123";
char g_i_buf3[]="123";
 
void after()
{
 
}
 
int main(int argc, char **argv)
{
        char l_buf[16];
        char l_buf2[16];
        char l_buf3[16];

 
        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);
 
        printf("g_i_buf: 0x%x\n", g_i_buf);
        printf("g_i_buf2: 0x%x\n", g_i_buf2);
        printf("g_i_buf3: 0x%x\n", g_i_buf3);
 
        printf("l_buf: 0x%x\n", l_buf);
        printf("l_buf2: 0x%x\n", l_buf2);
        printf("l_buf3: 0x%x\n", l_buf3);
 
 
        printf("before: 0x%x\n", before);
        printf("after: 0x%x\n", after);
        printf("main: 0x%x\n", main);
 
        if (argc > 1)
        {
                strcpy(l_buf, argv[1]);
        }
        return 0;
}

在这里插入图片描述
然后用gcc编译,再运行


 1. gcc -o c c.c
 2. ./c

运行结果如下:
在这里插入图片描述

其中,g_buf、g_buf2、g_buf3、g_buf4、g_i_buf、g_i_buf2、g_i_buf3为全局变量,他们的地址是递增的;l_buf、l_buf2、l_buf3、l_buf4是局部变量。

四、stm32堆、栈、全局变量的分配地址

使用之前串口通信的模板,分别在stm32中定义了全局变量和局部变量,并把它们的地址返回给windows,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文件,“load”,打开串口,按下stm32开发板上的复位键“RESET”,结果如下:
在这里插入图片描述 前3个part变量为局部变量,它们储存到了栈中,地址依次减小。
后三个global为全局变量,它们储存到了静态区,地址依次增加。

将main.c改为如下:

#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)
	{	
		
	}	
}

然后进行编译生成hex文件,“load”,打开串口,按下stm32开发板上的复位键“RESET”,结果如下:
在这里插入图片描述
前三个静态变量储存到了静态区,地址依次增加。
后三个指针储存到了堆中,地址依次增加。

结果分析

可以看到,从低地址到高地址,如图:
在这里插入图片描述

五、参考资料

https://www.pianshen.com/article/8285571527/
https://blog.csdn.net/jirryzhang/article/details/79518408
https://blog.csdn.net/feier7501/article/details/8564300

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值