stm32的串口通信以及全局变量、局部变量、堆、栈等概念

一、基于寄存器与基于固件库的stm32

基于寄存器与基于固件库的stm32 LED流水灯例子的编程方式差异比较:
1、基于寄存器方式的开发特点:
(1)具体参数更直观;
(2)程序运行占用资源少。
但是它的缺陷也不可忽视,如下:
(1)开发速度慢;
(2)程序可读性差;
(3) 维护复杂。
上述缺陷直接影响了开发效率,程序维护成本,交流成本。通常情况下,只有在频繁调用的中断服务函数时利用直接配置寄存器的方式。
2、基于固态库方式开发,也就是直接调用库函数,特点就是:
(1)外设交流方便;
(2)查错简单;
(3)对主控制器STM32上手简单。
总的来说基于寄存器:资料丰富,容易理解,适合新手学习。
基于固件库:可移植性强,更贴近底层,要求对工作原理有深入理解,适合有丰富经验的人使用。

二、STM32的USART串口通信程序实例

我们使用的是STM32F103,程序和软件资料由野火官方提供。
1.先在野火资料包里找到CH341SER.EXE,点击安装
在这里插入图片描述2.将USB线与stm32上的“USB转串口”连接,另一端接上电脑,将J-LINK线与stm32连接,另一端接电脑,可看见stm32亮红灯
在这里插入图片描述3、在官方资料库中找到USART1接发文件夹下的keil工程文件。
在这里插入图片描述4、将stm32f10x_it.c文件的串口中断服务函数和main.c的部分修改。
在这里插入图片描述在这里插入图片描述代码如下:
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!\n");
		delay(5000000);
	}	
}

5、编译生成hex文件
在这里插入图片描述这里用的是J-LINK,可以直接在keil上烧录程序到stm32上
先设置一下这个目标选项:
在这里插入图片描述在这里插入图片描述在这里插入图片描述最后烧录:
在这里插入图片描述6、打开官方资料包里的“野火多功能调试助手”,单击“打开串口”即可看到stm32向上机位发送消息。当我们输入“stop stm32!”时,stm32停止发送消息。
在这里插入图片描述

三、C语言程序里全局变量、局部变量、堆、栈等概念,在ubuntu系统中编程,输出信息进行验证

全局变量、静态局部变量保存在全局数据区,初始化的和未初始化的分别保存在一起。普通局部变量保存在堆栈中。
在C\C++中,通常可以把内存理解为4个分区:栈、堆、全局/静态存储区和常量存储区
(1) 内存栈区stack: 存放局部变量名;
(2) 内存堆区heap: 存放new或者malloc出来的对象;
(3)Text & Data & Bss:代码段与静态分配
(4) BSS区(未初始化数据段):并不给该段的数据分配空间,仅仅是记录了数据所需空间的大小。
(5)DATA(初始化的数据段):为数据分配空间,数据保存在目标文件中。
1.在ubuntu中新建一个1.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];
        static char s_buf[16];
        static char s_buf2[16];
        static char s_buf3[16];
        char *p_buf;
        char *p_buf2;
        char *p_buf3;
        
        p_buf = (char *)malloc(sizeof(char) * 16);
        p_buf2 = (char *)malloc(sizeof(char) * 16);
        p_buf3 = (char *)malloc(sizeof(char) * 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("s_buf: 0x%x\n", s_buf);
        printf("s_buf2: 0x%x\n", s_buf2);
        printf("s_buf3: 0x%x\n", s_buf3);
 
        printf("p_buf: 0x%x\n", p_buf);
        printf("p_buf2: 0x%x\n", p_buf2);
        printf("p_buf3: 0x%x\n", p_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;
}

执行后如下:
在这里插入图片描述可以看出,这些地址呈递增关系。

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

1.在之前的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)
	{
    
    	
		
	}	
}

2.编译生成hex文件,烧录到stm32中,打开串口调试助手,效果如下:
在这里插入图片描述可以看出这里前3个part为局部变量,位于栈中,地址逐个减小。
后3个global为全局变量,位于静态区,地址逐个增加。
3.再修改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)
	{
    
    	
		
	}	
}

4.打开串口调试助手,效果如下:
在这里插入图片描述
可以看出这里前3个静态变量位于静态区,地址依次增加。
后3个指针位于堆,地址依次增加。
总结:这次的实验让我学会了stm32的串口通信操作还了解了C语言中,局部变量、全局变量、静态变量、堆、栈的内存地址。