STM32串口通讯

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

嵌入式的编程,往下说就是操作MCU的寄存器。而固件库就是函数的集合,固件库函数的作用是向下负责与寄存器直接打交道,向上提供用户函数调用的接口(API)。相对于固件库的方式,直接写寄存器的代码更为简洁,只需要对指定的寄存器进行需要的操作就可以了,但是对于STM32来说,寄存器多达数百个,记起来也是一件非常让人头疼的事情。ST推出了官方固件库,固件库将这些寄存器底层操作都封装起来,提供一整套接口,你不需要去知道操作的是哪个寄存器,你只需要知道调用哪些函数即可。

二、STM32的USART窗口通讯程序

学习和阅读“零死角玩转STM32F103–指南者”文档中的第20、21章内容,完成STM32的USART窗口通讯程序,要求:
1)设置波特率为115200,1位停止位,无校验位。
2)STM32系统给上位机(win10)连续发送“hello windows!”,上位机接收程序可以使用“串口调试助手“,也可自己编程。
3)当上位机给stm32发送“Stop,stm32”后,stm32停止发送

  • 安装CH340驱动
    在这里插入图片描述
    在这里插入图片描述
  • 运行野火多功能调试助手

在这里插入图片描述

  • 打开如下
    在这里插入图片描述
  • keil5中打开所需工程,工程路径如下
    在这里插入图片描述
  • 修改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文件
    在这里插入图片描述
  • 使用mcuisp编程前需连接好单片机
    在这里插入图片描述
  • 设置好参数后开始编程
    在这里插入图片描述
  • 使用野火多功能助手,打开串口
    在这里插入图片描述
  • 开始收发消息,此时我们输入stop stm32!,显示收到,停止发送消息

在这里插入图片描述

三、C语言程序里局部变量、全局变量、静态变量、堆、栈的内存地址

参考:

C/C++程序内存的各种变量存储区域和各个区域详解

  • 在Ubuntu中新建.c文件,输入以下代码
#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++编译的程序占用的内存分为以下几个部分

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

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

  • 将任务二中的串口通讯工程中的main.c文件程序修改如下
#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);
	}	
}

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页