用STM32核心板实现STM32串口通讯

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

使用固件库,目前比较多的例程是使用固件库编写的。官方的例子也都采用固件库方式。特点就是简单,易于理解,资料多。如果你没有CortexM系列内核的开发基础,建议从固件库开始玩起。等有一定基础,或是特别需要时再用寄存器。

使用寄存器,想要深入理解CortexM3内核或是需要为了获得更好的可移植性,学习寄存器编程会比较有帮助。但是从专业的角度上看,寄存器更贴近底层,对外设的工作原理和运行机理会有更深的理解。

二、STM32的USART窗口通讯程序

完成这次任务用到的是stm32核心板,根据原理图连好线后应该如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ak5W4gQ4-1606888870617)(E:\大三学习\嵌入式系统开发\第六次作业\image\1.1.jpg)]

要求完成以下任务:

1)设置波特率为115200,1位停止位,无校验位。

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

3)当上位机给stm32发送“Stop,stm32”后,stm32停止发送。

续经过以下操作完成:

步骤1准备工作

1、keil5软件,版本最好在5.20以上,野火串口调试助手。

2、stm32核心板、usb转TTL线、TL-link下载线。

3、现成的keil工程(用于完成任务的工程代码,可在野火官网下载)

步骤2烧录

  • 打开现成的keil工程

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gVXtbi1s-1606888870620)(E:\大三学习\嵌入式系统开发\第六次作业\image\1.2.png)]

    打开后如下:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vv9q1H1J-1606888870623)(E:\大三学习\嵌入式系统开发\第六次作业\image\1.3.png)]

  • 将已经连接好的stm32核心板连接到电脑上

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NG4Y7GCG-1606888870627)(E:\大三学习\嵌入式系统开发\第六次作业\image\1.4.jpg)]

    打开设备管理器应该如下:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CLPDJ3xp-1606888870631)(E:\大三学习\嵌入式系统开发\第六次作业\image\0.png)]

    keil中进行编译,生成.axf文件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JI2zgEEf-1606888870633)(E:\大三学习\嵌入式系统开发\第六次作业\image\1.5.png)]

  • 点击魔术棒–>Debug–>ST-link Debugger

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ECTATMIZ-1606888870633)(E:\大三学习\嵌入式系统开发\第六次作业\image\1.6.png)]

    点击settings–>SW

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bexD7xOX-1606888870635)(E:\大三学习\嵌入式系统开发\第六次作业\image\1.7.png)]

    点击Flash Download–>Erase Full Chip–>add

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nwx179zd-1606888870636)(E:\大三学习\嵌入式系统开发\第六次作业\image\1.8.png)]

    添加完成后依次点确定,ok完成设置。

  • 进行烧录

    点击Download进行下载

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rkIr0GLt-1606888870637)(E:\大三学习\嵌入式系统开发\第六次作业\image\1.9.png)]

    下载完成后如图:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cnsAMO3A-1606888870638)(C:\Users\SN\AppData\Roaming\Typora\typora-user-images\image-20201202102556168.png)]

    至此,完成扫烧录。

步骤3打开野火调试助手,进行验证

具体过程如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hP1wSfrh-1606888870639)(E:\大三学习\嵌入式系统开发\第六次作业\image\2.gif)]

可以看到要求已经实现,会连续发送woshiweishien,输入Stop,stm32时,会停止发送。

相关代码:(因为在野火官网可以下载现成的,故只给出main函数部分)

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include <stdlib.h>
int hcr=1;

 int main(void)
 { 
    
    
  char stop[]={'S','t','o','p',',','s','t','m','3','2'};
 	u16 t;  
	u16 len;	
	u16 times=0;
	
	delay_init();	    	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	uart_init(115200);	
 	LED_Init();			   
	KEY_Init();         
	
 	while(hcr)
	{
		if(USART_RX_STA&0x8000)
		{		   
			len=USART_RX_STA&0x3fff;
			printf("\r\nhello windows!:\r\n\r\n");
			for(t=0;t<len&&USART_RX_BUF[t]==stop[t];hcr++,t++)
				{if (hcr>=10) {hcr=0;break;}}
				
				
			for(t=0;t<len;t++)
			{ 
				USART_SendData(USART1, USART_RX_BUF[t]);
				
				while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
			}
			printf("\r\n\r\n");//²åÈë»»ÐÐ
			USART_RX_STA=0;
		}
		
		else
		{
			times++;
			if(times%100==0)
			{
				printf("\r\nwoshiiweishen\r\n");	
			}
			delay_ms(10);   
		}
	}	 
 }

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

1、全局变量与局部变量

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

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

局部变量和全局变量的zhongh综合示例演示:

代码:

#include <stdio.h>

int n = 10;  //全局变量

void func1(){
    int n = 20;  //局部变量
    printf("func1 n: %d\n", n);
}

void func2(int n){
    printf("func2 n: %d\n", n);
}

void func3(){
    printf("func3 n: %d\n", n);
}

int main(){
    int n = 30;  //局部变量
    func1();
    func2(n);
    func3();
    //代码块由{}包围
    {
        int n = 40;  //局部变量
        printf("block n: %d\n", n);
    }
    printf("main n: %d\n", n);

    return 0;
}

在Ubuntu下编译运行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DPD5V45b-1606888870640)(E:\大三学习\嵌入式系统开发\第六次作业\image\2.0.png)]

分析:

  1. 对于 func1(),输出结果为 20,显然使用的是函数内部的 n,而不是外部的 n;func2() 也是相同的情况。

  2. func3() 输出 10,使用的是全局变量,因为在 func3() 函数中不存在局部变量 n,所以编译器只能到函数外部,也就是全局作用域中去寻找变量 n。

  3. { }包围的代码块也拥有独立的作用域,printf() 使用它自己内部的变量 n,输出 40。

  4. C语言规定,只能从小的作用域向大的作用域中去寻找变量,而不能反过来,使用更小的作用域中的变量。对于 main() 函数,即使代码块中的 n 离输出语句更近,但它仍然会使用 main() 函数开头定义的 n,所以输出结果是 30。

2、堆与栈

在 C 语言中,内存分配方式不外乎有如下三种形式:

  1. 从静态存储区域分配:它是由编译器自动分配和释放的,即内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在,直到整个程序运行结束时才被释放,如全局变量与 static 变量。
  2. 在栈上分配:它同样也是由编译器自动分配和释放的,即在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元将被自动释放。需要注意的是,栈内存分配运算内置于处理器的指令集中,它的运行效率一般很高,但是分配的内存容量有限。
  3. 从堆上分配:也被称为动态内存分配,它是由程序员手动完成申请和释放的。即程序在运行的时候由程序员使用内存分配函数(如 malloc 函数)来申请任意多少的内存,使用完之后再由程序员自己负责使用内存释放函数(如 free 函数)来释放内存。也就是说,动态内存的整个生存期是由程序员自己决定的,使用非常灵活。需要注意的是,如果在堆上分配了内存空间,就必须及时释放它,否则将会导致运行的程序出现内存泄漏等错误。

堆与栈的综合示例演示:

代码:

#include <stdio.h>
#include <malloc.h>
int main(void)
{
    /*在栈上分配*/
    int  i1=0;
    int  i2=0;
    int  i3=0;
    int  i4=0;
    printf("栈:向下\n");
    printf("i1=0x%08x\n",&i1);
    printf("i2=0x%08x\n",&i2);
    printf("i3=0x%08x\n",&i3);
    printf("i4=0x%08x\n\n",&i4);
     printf("--------------------\n\n");
    /*在堆上分配*/
    char  *p1 = (char *)malloc(4);
    char  *p2 = (char *)malloc(4);
    char  *p3 = (char *)malloc(4);
    char  *p4 = (char *)malloc(4);
    printf("p1=0x%08x\n",p1);
    printf("p2=0x%08x\n",p2);
    printf("p3=0x%08x\n",p3);
    printf("p4=0x%08x\n",p4);
    printf("堆:向上\n\n");
    /*释放堆内存*/
    free(p1);
    p1=NULL;
    free(p2);
    p2=NULL;
    free(p3);
    p3=NULL;
    free(p4);
    p4=NULL;
    return 0;
}

在Ubuntu下编译运行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P88KUnqb-1606888870640)(E:\大三学习\嵌入式系统开发\第六次作业\image\2.1.png)]

分析:

从运行结果中不难发现,内存中的栈区主要用于分配局部变量空间,处于相对较高的地址,其栈地址是向下增长的;而堆区则主要用于分配程序员申请的内存空间,堆地址是向上增长的。

四、重温C语言程序里全局变量、局部变量、堆、栈等概念,在Keil中针对stm32系统进行编程,调试变量,进行验证; 通过串口输出信息到上位机,进行验证。

1、栈区(stack)

临时创建的局部变量存放在栈区。
函数调用时,其入口参数存放在栈区。
函数返回时,其返回值存放在栈区。
const定义的局部变量存放在栈区。

2、堆区(heap)

堆区用于存放程序运行中被动态分布的内存段,可增可减。
可以有malloc等函数实现动态分布内存。
有malloc函数分布的内存,必须用free进行内存释放,否则会造成内存泄漏。

3、.bss段

未初始化的全局变量存放在.bss段。
初始化为0的全局变量和初始化为0的静态变量存放在.bss段。
.bss段不占用可执行文件空间,其内容有操作系统初始化。

4、.data段

已经初始化的全局变量存放在.data段。
静态变量存放在.data段。
.data段占用可执行文件空间,其内容有程序初始化。
const定义的全局变量存放在.rodata段。

在串口通信工程中将main函数代码改成如下:

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include <stdlib.h>

int k1 = 1;
int k2;
static int k3 = 2;
static int k4;



 int main(void)
 { 
  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); 
 	u16 t;  
	u16 len;	
	u16 times=0;
	free(p1);
  free(p2);
	delay_init();	    	 //ÑÓʱº¯Êý³õʼ»¯	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //ÉèÖÃNVICÖжϷÖ×é2:2λÇÀÕ¼ÓÅÏȼ¶£¬2λÏìÓ¦ÓÅÏȼ¶
	uart_init(115200);	 //´®¿Ú³õʼ»¯Îª115200
 	LED_Init();			     //LED¶Ë¿Ú³õʼ»¯
	KEY_Init();          //³õʼ»¯Óë°´¼üÁ¬½ÓµÄÓ²¼þ½Ó¿Ú
	
 	while(1)
	{	
			for(t=0;t<len;t++)
			{ 
				USART_SendData(USART1, USART_RX_BUF[t]);//Ïò´®¿Ú1·¢ËÍÊý¾Ý
				
				while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//µÈ´ý·¢ËͽáÊø
			}
	
			USART_RX_STA=0;
    	times++;
			if(times%500==0)
			{
				printf("\r\nǶÈëʽ´®¿ÚʵÑé\r\n");
				printf("hcr@2219491180qqcom\r\n\r\n");
	      printf("Õ»Çø-±äÁ¿µØÖ·\r\n");
				printf("                i:%p\r\n", &i);
				printf("                p:%p\r\n", &p);
				printf("              str:%p\r\n", str);
        printf("\n¶ÑÇø-¶¯Ì¬ÉêÇëµØÖ·\r\n");
        printf("                   %p\r\n", p1);
        printf("                   %p\r\n", p2);
        printf("\r\n.bss¶Î\r\n");
        printf("\nÈ«¾ÖÍⲿÎÞ³õÖµ k2£º%p\r\n", &k2);
        printf("¾²Ì¬ÍⲿÎÞ³õÖµ k4£º%p\r\n", &k4);
        printf("¾²Ì¬ÄÚ²¿ÎÞ³õÖµ m2£º%p\r\n", &m2);
        printf("\r\n.data¶Î\r\n");
        printf("\nÈ«¾ÖÍⲿÓгõÖµ k1£º%p\r\n", &k1);
        printf("¾²Ì¬ÍⲿÓгõÖµ k3£º%p\r\n", &k3);
        printf("¾²Ì¬ÄÚ²¿ÓгõÖµ m1£º%p\r\n", &m1);
        printf("\r\n³£Á¿Çø\n");
        printf("ÎÄ×Ö³£Á¿µØÖ·     £º%p\r\n",var1);
        printf("ÎÄ×Ö³£Á¿µØÖ·     £º%p\r\n",var2);
        printf("\r\n´úÂëÇø\n");
        printf("³ÌÐòÇøµØÖ·       £º%p\n",&main);
				printf("\r\n end \r\n\r\n\r\n");
			}
			
			delay_ms(10);   
		}
	}	 
 


在keil中如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R7eXloYF-1606888870642)(E:\大三学习\嵌入式系统开发\第六次作业\image\3.0.png)]

在进行烧录,烧录过程在STM32的USART窗口通讯程序中已经给出。

打开野火调试助手查看运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PQRniCTy-1606888870643)(E:\大三学习\嵌入式系统开发\第六次作业\image\3.gif)]

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值