STM32串口通信与它的堆、栈、全局变量



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

寄存器:可移植性强,更贴近底层,寄存器版式直接对内部寄存器进行操作

固件库:是用ST提供的库函数开发,有函数的集合,不需要与寄存器直接打教导,提供用户函数调用的API
————————————————————————

概念了解:
1.串口通信是指外设和计算机间,通过数据信号线 、地线、控制线等,按位进行传输数据的一种通讯方式,它将需要传输的数据通过串口按位(bit)发送和接收字节。
分类:单工、 半双工、 全双工

2.USART是一个串行通信设备,可以灵活地与外部设备进行全双工数据交换。

二、STM32的USART窗口通讯程序

1、烧录准备

开发板:野火指南者(STM32F103)

STM32库版本:STM32F10x_StdPeriph_Lib_V3.5.0

IDE:KEIL5
在这里插入图片描述
用usb线把stm32开发板的 ‘usb转串口’和电脑相连接,打开开关,小灯亮起。
计算机与调制调解器的信号线连接:
在这里插入图片描述
在这里插入图片描述
打开CH341SER.EXE,安装。

在这里插入图片描述
打开串口下载助手mcuisp
①搜索串口,设置波特率 115200(尽量不要设置的太高)
②选择要下载的 HEX 文件
③校验、编程后执行
④DTR 低电平复位,RTS 高电平进入 bootloader
⑤开始编程
在这里插入图片描述

2、代码

要求:
1.设置波特率为115200,1位停止位,无校验位。
2.STM32系统给上位机(win10)连续发送“hello windows!”,上位机接收程序可以使用“串口调试助手“,也可自己编程。
3.当上位机给stm32发送“Stop,stm32”后,stm32停止发送。
在这里插入图片描述
把其中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语言程序里全局变量、局部变量、堆、栈等概念

1、在ubuntu系统中编程,输出信息进行验证

(1)栈区(stack):由编译器自动分配和释放,存放函数的参数值、局部变量的值等,其操作方式类似于数据结构中的栈。
(2)堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收。分配方式类似于数据结构中的链表。
(3)全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统自动释放。
(4)文字常量区:常量字符串就是存放在这里的。
(5)程序代码区:存放函数体的二进制代码。

代码:

#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个局部变量的地址
在这里插入图片描述
定义了4个局部变量,并输出它们的地址,地址是递增的。
在这里插入图片描述

2、在Keil中针对stm32系统进行编程,通过串口输出信息到上位机,进行验证

堆栈:堆和栈都是动态分配内存,两者空间大小都是可变的。
栈:存放Automatic Variables,按内存地址由高到低方向生长,其最大大小由编译时确定,速度快,但自由性差,最大空间不大。
堆:自由申请的空间,按内存地址由低到高方向生长,其大小由系统内存/虚拟内存上限决定,速度较慢,但自由性大,可用空间大。

每个线程都会有自己的栈,但是堆空间是共用的。

#include "stm32f10x.h"
#include "bsp_usart.h"
#include <stdio.h>
#include <stdlib.h>
int k1 = 1;
int k2;
static int k3 = 2;
static int k4;

void delay(uint32_t count)
{
	while(count--);
}
int main(void)
{	
  USART_Config();
  while(1)
	{	
		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);
	delay(5000000);
	}	
}


在这里插入图片描述

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

在这里插入图片描述
在这里插入图片描述
前三个静态变量储存到了静态区,地址依次增加。
后三个指针储存到了堆中,地址依次增加。

栈在顶层(地址最大),然后依次是堆,静态区。

总结

参考:零死角玩转STM32F103–指南者 第20、21章内容
参考一
参考二

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值