STM32的串口通讯

一、寄存器与固件库的stm32 LED流水灯例子的编程方式差异比较

外设库函数的调用与直接配置寄存器相比,从执行效率上看会有额外的消耗:初始化变量赋值的过程、库函数在被调用的时候要耗费调用时间;在函数内部,对输入参数转换所需要的额外运算也消耗一些时间。
1、基于寄存器方式的开发特点:
(1)具体参数更直观;
(2)程序运行占用资源少。
但是它的缺陷也不可忽视,如下:
(1)开发速度慢;
(2)程序可读性差;
(3) 维护复杂。
上述缺陷直接影响了开发效率,程序维护成本,交流成本。通常情况下,只有在频繁调用的中断服务函数时利用直接配置寄存器的方式。
2、基于固态库方式开发,也就是直接调用库函数,特点就是:
(1)外设交流方便;
(2)查错简单;
(3)对主控制器STM32上手简单。

二、STM32的行口通讯

开发板:野火指南者(STM32F103VE)带3.2寸屏
代码编译:Keil5
USBQ驱动:CH340

1.检查开发板的完整性
在这里插入图片描述
2、再将开发板上的开关转到“ON”,旁边的LED灯亮起
在这里插入图片描述
3、安装CH340驱动
在这里插入图片描述
4、下载野火串口调试助手v1.0.1.5
在这里插入图片描述
5、串口通信的验证代码,厂家已经给我们准备好,我们只需要调试代码
在这里插入图片描述
在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);
	}	
}


6.进行烧录
(1)确保电脑与开发板驱动连接成功
在这里插入图片描述
(2)再到keil中进行debug设置
在这里插入图片描述

在这里插入图片描述
(3)之后点击编译下载烧录即可,如下
在这里插入图片描述
此时在野火串口调试助手点击“打开串口”即为显示stm32正在向上机位发送消息。当我们输入“stop stm32!”时,stm32停止发送消息。
在这里插入图片描述

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

首先编写一个C语言程序,输入到Ubantu下

#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 内存栈区stack: 存放局部变量名;
2. 内存堆区heap: 存放new或者malloc出来的对象;
3. Text & Data & Bss:代码段与静态分配
4. BSS区(未初始化数据段):并不给该段的数据分配空间,仅仅是记录了数据所需空间的大小。
5.DATA(初始化的数据段):为数据分配空间,数据保存在目标文件中。

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

1、在Keil中针对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)
	{
    
    	
		
	}	
}

我们进行程序烧录后:
在这里插入图片描述
显然:
part1、part2、part3为栈中的局部变量,地址逐渐减小。
global1、global2、global3为静态区中的全局变量,地址逐渐增加。

2.之后再次修改main函数

#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、st2、st3都是静态变量,他们的地址依次增加。
p1、p2、p3是堆中的指针,他们的地址也是依次增加。

猜你喜欢

转载自blog.csdn.net/weixin_47357131/article/details/110495349