ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

STM32串口通讯及C程序编译后内存地址的分配

2020-12-02 19:33:12  阅读:293  来源: 互联网

标签:char 16 buf3 串口 STM32 printf 内存地址 buf 0x%


文章目录


提示:以下是本篇文章正文内容,下面案例可供参考

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

寄存器:贴近底层,更好理解工作原理
固件库:简单易学,资料多

二、STM32的USART窗口通讯程序

笔者使用的是stm32f103指南者
程序及软件由官方提供: 官方下载链接

2.1将STM32开发板上的“USB转串口”通过USB线与电脑相连接,打开STM32开发板开关可观察到STM32开发板上有红灯亮起
在这里插入图片描述

2.2在下载资料中找到CH341SER.EXE并安装
在这里插入图片描述
2.3代码实现

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

打开官方资料中下载的
书籍配套例程-F103VE指南者\21-USART—串口通信\USART1接发\Project\RVMDK(uv5\BH-F103.uvprojx
在这里插入图片描述
修改USER下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文件
在这里插入图片描述

2.4运行串口下载软件mcuisp.exe并设置波特率为115200
在这里插入图片描述

添加hex文件
在这里插入图片描述
校验、编程后执行、DTR 低电平复位,RTS 高电平进入 bootloader、开始编程
在这里插入图片描述
执行结果
在这里插入图片描述
打开野火多功能调试助手,并选择打开串口,最终效果如下
在这里插入图片描述

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

3.1C语言程序部分概念

全局变量:全局变量既可以是某对象函数创建,也可以是在本程序任何地方创建。全局变量是可以被本程序所有对象或函数引用。

局部变量:也称内部变量,是指在一个函数内部或复合语句内部定义的变量 。局部变量的作用域是定义该变量的函数或定义该变量的复合语句。局部变量的生存期是从函数被调用的时刻算起到函数返回调用处的时刻结束。

栈:
通常是用于那些在编译期间就能确定存储大小的变量的存储区,用于在函数作用域内创建,在离开作用域后自动销毁的变量的存储区。通常是局部变量,函数参数等的存储区。他的存储空间是连续的,两个紧密挨着定义的局部变量,他们的存储空间也是紧挨着的。栈的大小是有限的,通常Visual C++编译器的默认栈的大小为1MB,所以不要定义int a[1000000]这样的超大数组。
栈作为C语言中一种常用的数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。栈具有记忆作用,对栈的插入与删除操作中,不需要改变栈底指针。
栈是允许在同一端进行插入和删除操作的特殊线性表。允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为进栈(PUSH),删除则称为退栈(POP)。栈也称为后进先出表。

堆: 通常是用于那些在编译期间不能确定存储大小的变量的存储区,它的存储空间是不连续的,一般由malloc(或new)函数来分配内存块,并且需要用free(delete)函数释放内存。如果程序员没有释放掉,那么就会出现常说的内存泄漏问题。需要注意的是,两个紧挨着定义的指针变量,所指向的malloc出来的两块内存并不一定的是紧挨着的,所以会产生内存碎片。另外需要注意的一点是,堆的大小几乎不受限制,理论上每个程序最大可达4GB。

3.2验证

在这里插入图片描述

代码如下:

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

在这里插入图片描述
由上图结果可知:
在这里插入图片描述
该图来源

代码如下(示例):

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import  ssl
ssl._create_default_https_context = ssl._create_unverified_context

四、stm32系统进行编程,调试变量,进行验证

打开之前使用的野火21-USART—串口通信模板中的文件,将main.c改为如下:

#include "stm32f10x.h"
#include "bsp_usart.h"

char one1[16];     //全局变量
char one2[16];
char one3[16];
	
int main(void)
{	
  char two1[16];    //局部变量
  char two2[16];
  char two3[16];

  USART_Config();

  printf("two1: 0x%p\n", two1);
  printf("two2: 0x%p\n", two2);
  printf("two3: 0x%p\n", two3);
	 
  printf("one1: 0x%p\n", one1);
  printf("one2: 0x%p\n", one2);
  printf("one3: 0x%p\n", one3);
  while(1)
	{	
		
	}	
}

编译并生成hex文件
在这里插入图片描述
使用mcuisp烧录hex文件
在这里插入图片描述
打开野火多功能调试助手,点击打开串口,点击stm32开发板上的reset按钮
在这里插入图片描述
two变量为局部变量,储存到了栈中,地址依次减小
one变量为全局变量,储存到了静态区,地址依次增加
再将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文件
在这里插入图片描述
使用mcuisp烧录hex文件
在这里插入图片描述

打开野火多功能调试助手,点击打开串口,点击stm32开发板上的reset按钮
在这里插入图片描述
st静态变量储存到了静态区,地址依次增加
p指针储存到了堆中,地址依次增加

由上可得知:
代码(text)、data(gvar)、bss 在内存中地址较低低的位置(low level address),而堆栈则在相对较搞的位置。
堆(Heap)往高地址方向生长,栈(Stack)往低地址方向生长。
在这里插入图片描述

参考博客:
C/C++程序内存的各种变量存储区域和各个区域详解
C语言中,局部变量、全局变量、静态变量、堆、栈的内存地址

标签:char,16,buf3,串口,STM32,printf,内存地址,buf,0x%
来源: https://blog.csdn.net/metanoiah/article/details/110430419

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有