STM32串口通信

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

(1)使用固件库,目前比较多的例程是使用固件库编写的。官方的例子也都采用固件库方式。特点就是简单,易于理解,资料多。如果你没有CortexM系列内核的开发基础,建议从固件库开始玩起。等有一定基础,或是特别需要时再用寄存器。
(2)使用寄存器,想要深入理解CortexM3内核或是需要为了获得更好的可移植性,学习寄存器编程会比较有帮助。但是从专业的角度上看,寄存器更贴近底层,对外设的工作原理和运行机理会有更深的理解。

2、STM32的USART窗口通讯程序

我使用的是stm32f103指南者,需要的软件程序
在这里插入图片描述
下载连接: 野火STM32F103指南者开发板.
然后用usb线把stm32开发板和电脑相连接,stm32端连接的 ‘usb转串口’这个接口,再打开stm32开关,可以看到红色的小灯亮起。
在这里插入图片描述
连接过后打开CH341SER.EXE,点击安装,显示安装成功即可。

在这里插入图片描述
然后打开串口下载助手mcuisp
在这里插入图片描述
按如下方式配置:①搜索串口,设置波特率 115200(尽量不要设置的太高) ,②选择要下载的 HEX 文件、③校验、编程后执行、④DTR 低电平复位,RTS 高电平进入 bootloader、⑤开始编程。(前4步一定要调试正确,否则可能连接不上)
在这里插入图片描述

代码及实现功能

1)设置波特率为115200,1位停止位,无校验位。
2)STM32系统给上位机(win10)连续发送“hello windows!”,
3)当上位机给stm32发送“Stop stm32!”后,stm32停止发送。

在所给连接中下载所需的代码,在此基础上,更改、调试,实现上述功能在这里插入图片描述
进入所下载的工程,解压后打开第21个串口通信文件中的USART1接发中的工程文件


找到所需的工程文件
在这里插入图片描述

实践操作及结果

打开工程文件,在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文件,在KEIL中点击魔法棒的图标,在Output中选择
在这里插入图片描述
编译
在这里插入图片描述
将生成.hex文件烧到,开始编程
在这里插入图片描述
在这里插入图片描述
打开串口调试助手,点击打开串口
在这里插入图片描述
在发送区,输入Stop,stm32!,发送数据
在这里插入图片描述
串口就会回复收到!
在这里插入图片描述

3. 全局变量、局部变量、堆、栈等,在ubuntu系统中的编程

1、全局变量

在所有函数外部定义的变量称为全局变量(Global Variable),它的作用域默认是整个程序,也就是所有的源文件,包括 .c 和 .h 文件。例如:

int a, b;  //全局变量
void func1(){
    //TODO:
}
float x,y;  //全局变量
int func2(){
    //TODO:
}
int main(){
    //TODO:
    return 0;
}

a、b、x、y 都是在函数外部定义的全局变量。C语言代码是从前往后依次执行的,由于 x、y 定义在函数 func1() 之后,所以在 func1() 内无效;而 a、b 定义在源程序的开头,所以在 func1()、func2() 和 main() 内都有效。

2、局部变量

定义在函数内部的变量称为局部变量(Local Variable),它的作用域仅限于函数内部, 离开该函数后就是无效的,再使用就会报错。例如:

int f1(int a){
    int b,c;  //a,b,c仅在函数f1()内有效
    return a+b+c;
}
int main(){
    int m,n;  //m,n仅在函数main()内有效
    return 0;
}
  1. 在 main 函数中定义的变量也是局部变量,只能在 main 函数中使用;同时,main 函数中也不能使用其它函数中定义的变量。main 函数也是一个函数,与其它函数地位平等。2) 形参变量、在函数体内定义的变量都是局部变量。实参给形参传值的过程也就是给局部变量赋值的过程。3) 可以在不同的函数中使用相同的变量名,它们表示不同的数据,分配不同的内存,互不干扰,也不会发生混淆。4) 在语句块中也可定义变量,它的作用域只限于当前语句块。

3、ubantu下变量的编程

编程代码如下:(全局变量)

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

该代码定义了4个全局变量并输出它们的地址
在这里插入图片描述
全局变量是按空间分配是按照声明变量的字母顺序按照空间递增顺序进行分配的,所以地址的顺序也是递增的
编程代码:(局部变量)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


int main()
{

        char l_buf[16];
        char l_buf2[16];
        char l_buf3[16];
        printf("l_buf: 0x%x\n", l_buf);
        printf("l_buf2: 0x%x\n", l_buf2);
        printf("l_buf3: 0x%x\n", l_buf3);
 
}

定义了三个局部变量
在这里插入图片描述
局部变量的地址值应该是递减的,而这里是递增的,本人也不清楚ubantu下地址分配的机理

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

1、全局变量和局部变量

在之前串口通信做修改,将main.c函数改为

#include "stm32f10x.h"
#include "bsp_usart.h"
char s1[16];
char s2[16];
char s3[16];//全局变量
void main()
{
	char a1[16];
	char a2[16];
	char a3[16];//局部变量
	USART_Config();
	printf("全局变量的地址是");printf("\n");
	printf("0x%p\n",s1);
	printf("0x%p\n",s2);
	printf("0x%p\n",s3);
	printf("局部变量的地址是");printf("\n");
	printf("0x%p\n",a1);
    printf("0x%p\n",a2);
    printf("0x%p\n",a3);
	while(1)
	{
	}
}

这里直接复制到Keil中时,可能有点不一致,需要将汉字重新输入
生成hex文件后,烧录到stm32中,打开串口调试助手,点击打开串口,然后点击stm32上的reset按钮,就可以看到如下结果。
在这里插入图片描述
全局变量的地址值是依次增大的,储存在堆区;局部变量的地址值是依次减小的,储存在栈区

2、静态变量和指针

再将main.c中的代码改为:

#include "stm32f10x.h"
#include "bsp_usart.h"
static char s1[16];
static char s2[16];
static char s3[16];//静态全局变量
void main()
{
	static char a1[16];
	static char a2[16];
	static char a3[16];//静态局部变量
	char *p1;
	char *p2;
	char *p3;//指针变量
	USART_Config();
	printf("全局变量的地址是");printf("\n");
	printf("0x%p\n",s1);
	printf("0x%p\n",s2);
	printf("0x%p\n",s3);
	printf("局部变量的地址是");printf("\n");
	printf("0x%p\n",a1);
  printf("0x%p\n",a2);
  printf("0x%p\n",a3);
	p1= (char *)malloc(sizeof(char) *16);
	p2= (char *)malloc(sizeof(char) *16);
	p3= (char *)malloc(sizeof(char) *16);
	printf("指针变量的地址是");printf("\n");
	printf("0x%p\n",p1);
	printf("0x%p\n",p2);
	printf("0x%p\n",p3);
	while(1)
	{
	}
}

在串口助手的输出为
在这里插入图片描述
可见,不管是静态全局变量、静态局部变量还是指针变量的地址都是递增的,全局变量和静态变量的存储是放在一块的都放在全局区(静态区);由malloc分配的内存是在堆区

参考网址:
浅析栈区和堆区内存分配的区别.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值