基于STM32F103嵌入式实验指导书.docx
《基于STM32F103嵌入式实验指导书.docx》由会员分享,可在线阅读,更多相关《基于STM32F103嵌入式实验指导书.docx(26页珍藏版)》请在冰点文库上搜索。
基于STM32F103嵌入式实验指导书
实验一、STM32的开发环境与简单工程
一、实验目的
1、熟悉STM32开发板的开发环境;
2、熟悉MDK创立和配置STM32工程工程的根本流程;
3、熟悉STM32官方库的应用;
4、标准编程格式。
二、实验内容
本次实验配置MDK集成开发环境,新建一个简单的工程文件,添加STM32官方库并配置工程,编译运行这个工程文件。
下载已经编译好的文件到开发板中运行。
学会在程序中设置断点,观察系统内存和变量,为调试应用程序打下根底。
三、预备知识
根本单片机硬件知识、单片机软件编程语言、程序创立和调试的根本方法。
四、实验设备及工具
硬件:
STM32开发平台
软件:
STM32官方库;PC机操作系统Windows98、Windows2000或WindowsXP;KEILMDK集成开发环境;串口转usb驱动。
五、实验步骤
1、在准备存放工程文件的目录下创立一新文件夹,命名为Proj_GPIO;在Proj_GPIO文件夹里面分别再创立四个文件夹:
CMSIS、USER、LIB、OBJ。
如图1。
其中CMSIS〔CortexMicrocontrollerSoftwareInterfaceStandard〕用于存放Cortex-M处理器系列的与供给商无关的软件抽象层和启动相关的代码文件;
USER用于存放我们自己编写的代码文件〔含自己移植的底层驱动〕,还有MDK工程;
LIB存放所有的官方底层驱动库文件;
OBJ用于工程输出的过程文件和最终的二进制文件。
图1
2、将官方库解压。
1〕把STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\CoreSupport下的所有文件和STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x下的所有文件都到第一步所创立的CMSIS文件夹中;
2〕把STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver目录下的文件〔目录inc和scr〕复制到第一步创立的LIB文件夹中;
3)把STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Template目录下的、、三个文件复制到USER文件夹中。
3、翻开MDK软件,新建一个工程Proj_GPIO保存到Proj_GPIO/USER中。
CPU选择STM32F103ZE,如图2;
图2
4、新建一个空文档main.c保存到USER中,然后根据绝对路径将文件对应添加到工程中,如右图。
5、配置工程属性,右键点击工程文件中的Target1选择OptionsforTarget‘Target1’翻开工程选项对话框。
做如下修改:
1〕Output选项勾选CreateHEXFile,然后点击SelectFolderforObjects按钮定位输出文件保存目录到工程的OBJ文件;
2〕Listing选项,同样点击SelectFolderforListings定位输出文件保存目录到工程的OBJ文件;
3〕C/C++选项,Define中填入STM32F10X_HD,USE_STDPERIPH_DRIVER系统的两个根本宏定义;配置IncludePaths属性,参加工程中包含头文件的目录;如右图
4〕后面Debug和Utilities两个选项如果使用J-link或者其他调试器那么需要做对应的修改,否那么不用。
6、根据实验任务硬件原理图编写代码实现四个按键控制led灯亮灭。
1〕其中用户按键和LED原理图如下:
图5
2〕根据原理图初始化各IO引脚,编写控制函数,然后主函数中调用。
/*********************************************************************
*函数名称:
io_init
*函数功能:
初始化PA0PE2PE3PE4为输入口PE5PB5为输出口
*参数:
无
*********************************************************************/
voidio_init()
{
GPIO_InitTypeDefgpin_init_struct;
//使能每个IO口的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
gpin_init_struct.GPIO_Pin=GPIO_Pin_0;//PA0引脚
gpin_init_struct.GPIO_Speed=GPIO_Speed_2MHz;//IO速度为2MHz
gpin_init_struct.GPIO_Mode=GPIO_Mode_IPD;//下拉模式
GPIO_Init(GPIOA,&gpin_init_struct);//A口按键
gpin_init_struct.GPIO_Pin=GPIO_Pin_5;
gpin_init_struct.GPIO_Speed=GPIO_Speed_2MHz;
gpin_init_struct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOB,&gpin_init_struct);//B口led1
GPIO_Init(GPIOE,&gpin_init_struct);//E口led2
gpin_init_struct.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;
gpin_init_struct.GPIO_Speed=GPIO_Speed_2MHz;
gpin_init_struct.GPIO_Mode=GPIO_Mode_IPU;//上拉模式
GPIO_Init(GPIOE,&gpin_init_struct);//E口按键
}
、
3〕代码编写完成后编译链接,通过下载软件将hex文件下载到实验板中运行验证。
实验二、ucos操作系统的移植
一、实验目的
1、掌握ucos到STM32的移植方法;
2、熟悉通过C语音处理底层存放器的技巧;
3、了解STM32在ucos任务切换时的处理;
4、标准编程格式。
二、实验内容
本次实验通过用C语言编写6个操作系统相关函数和用汇编语言编写4个与处理器相关的函数,将实时操作系统µC/OS-Ⅱ移植到芯片STM32F103ZE中,并创立两个用户任务点亮led。
学会操作系统的移植方法,深入掌握嵌入式操作系统µC/OS-Ⅱ在初始化任务和任务调度的实现方法,直观了解实时操作系统的体系构造和设计思想。
三、预备知识
根本单片机硬件知识、单片机软件编程语言、程序创立和调试的根本方法、ucos操作系统的任务调度原理、STM32的存放器架构。
四、实验设备及工具
硬件:
STM32开发平台
软件:
STM32官方库;PC机操作系统Windows98、Windows2000或WindowsXP;KEILMDK集成开发环境;串口转usb驱动。
五、实验步骤
1、按实验一的步骤新建一个工程Proj2_ucos。
2、将移植好的ucos源代码整个拷贝到我们的新建的工程目录中,然后按对应的文件路径添加到keil工程里〔os_dbg.c和os_dbg_r.c只添加一个〕,如图6和图7。
图6图7
PendSV_Handler函数注释掉,main文件中将includes.h包含进来,主函数为空,编译通过。
4、建立sys_init()函数编写操作系统运行需要的硬件相关初始化〔见代码〕,然后修改stm32f10x_it.c中的系统心跳中断函数〔见代码,〕。
5、编写用户任务函数和相关的初始化。
6、最后在主函数中创立任务并启动操作系统。
编译并调试运行。
#include"stm32f10x.h"
#include"includes.h"
#defineLED2_ONGPIO_ResetBits(GPIOB,GPIO_Pin_5)
#defineLED2_OFFGPIO_SetBits(GPIOB,GPIO_Pin_5)
#defineLED1_ONGPIO_ResetBits(GPIOE,GPIO_Pin_5)
#defineLED1_OFFGPIO_SetBits(GPIOE,GPIO_Pin_5)
OS_STKtask_stk[128];
voidmy_task(void);
voidled_init(void);
voidsys_init(void);
intmain()
{
OSInit();
OSTaskCreate(my_task,(void*)0,(OS_STK*)&task_stk[127],10);
OSStart();
while
(1);
}
实验三、ucos操作系统的任务通信
一、实验目的
1、掌握ucos任务间通信的各种方法;
2、了解嵌入式操作系统任务间可能出现的资源冲突;
3、掌握ucos中信号量和邮箱的应用;
4、标准编程格式。
二、实验内容
本次实验通过用C语言编写基于ucos操作系统下的多个用户任务,并且实现任务间的正确通信。
通过信号量处理公共资源的等待和使用,通过邮箱实现任务间的多个数据变量的传递。
建立正确的操作系统编程理念,深入掌握µC/OS-Ⅱ中信号量与邮箱的创立和使用,了解各任务间通信方法的大概原理及优缺点。
三、预备知识
根本单片机硬件知识、单片机软件编程语言、程序创立和调试的根本方法、ucos操作系统的任务调度原理。
四、实验设备及工具
硬件:
STM32开发平台。
软件:
STM32官方库;PC机操作系统Windows98、Windows2000或WindowsXP;KEILMDK集成开发环境;串口转usb驱动。
五、实验步骤
1、建立基于操作系统µC/OS-Ⅱ的工程Proj3_ucos1,并配置好工程各项属性。
.h两个文件,详细代码如下。
#ifndef_MY_TASK_H
#define_MY_TASK_H
#include"includes.h"
externOS_EVENT*NUM_COUNT;
externvoidmy_task(void);
#endif
NUM_COUNT1和NUM_COUNT2,两个变量在my_task函数里用于记录该任务循环的总次数,区别在与NUM_COUNT1直接操作,而NUM_COUNT2那么通过信号量的方法进展操作。
3、在main函数中初始化操作系统后创立一个信号量NUM_COUNT,然后用OSTaskCreate创立两个任务,优先级分别是8和9,两个任务的入口地址都是task1.c文件中的my_task函数。
NUM_COUNT=OSSemCreate
(1);//创立一个信号量
OSTaskCreate(my_task,(void*)0,(OS_STK*)&task1_stk[SIZE_STK-1],9);
OSTaskCreate(my_task,(void*)0,(OS_STK*)&task2_stk[SIZE_STK-1],8);
4、编译通过后调试,在debug界面中,将NUM_COUNT1,NUM_COUNT2两个全局变量参加到变量观察窗口watch1中,然后在task.c的my_task函数里面设置断点,运行并观察两个变量的变化,理解信号量的使用。
5、关于操作系统邮箱的应用由例子工程Proj3_ucos2实现,请自行理解代码。
实验四、ucos操作系统的文件系统实现
一、实验目的
1、了解文件系统FATFS的根本实现原理;
2、掌握FATFS的移植步骤;
3、掌握基于ucos中FATFS的应用;
4、掌握STM32对SD卡的读写操作;
5、标准编程格式。
二、实验内容
本实验实现将FAT文件系统移植到ucos中,并基于ucos的文件系统编写用户任务进展测试,通过对文件系统的移植实验深入掌握对嵌入式相关驱动移植的根本步骤,建立正确的嵌入式操作系统驱动移植理念,并且熟悉掌握ucos操作系统下的文件系统的根本应用,了解其优缺点。
三、预备知识
根本单片机硬件知识、单片机软件编程语言、程序创立和调试的根本方法、ucos操作系统的任务调度原理、STM32单片机中的SD卡驱动、文件系统的操作函数、FAT文件系统的根底知识。
四、实验设备及工具
硬件:
STM32开发平台。
软件:
PC机操作系统Windows98、Windows2000或WindowsXP;KEILMDK集成开发环境;串口转usb驱动;STM32官方库;FATFS的官方库;STM32的uart驱动和SD卡驱动源码。
五、实验步骤
1、拷贝实验三的所有代码到新的目录地下,删除USER和OBJ文件夹里工程相关的文件,重新建立实验四的工程并命名为Proj4_FATFS,配置好工程各项属性。
2、在USER文件夹里面创立文件夹myapp,将串口驱动uart和SD卡驱动sdio_sdcard的源代码拷贝到该文件夹里面,并添加到工程中USER。
3、拷贝FAT文件系统源码到myapp文件夹。
在keil的工程中增加一个文件夹FATFS并添加diskio.c、ff.c、cc936.c三个文件到里面,如右图。
4、尝试编译字符表文件cc936.c可能发现出错:
#errordirective:
Thisfileisnotneededincurrentconfiguration._CODE_PAGE这个宏的定义值不是936和长文件名宏定义_USE_LFN的值不是1导致的。
修改成对应的值后该文件的编译即可通过〔如果用其他字符表文件同理〕。
5、移植FAT文件系统需要做的事情。
1〕FATFS是一个通用的文件系统模块,用于在小型嵌入式系统中实现FAT文件系统。
FatFs的编写遵循ANSIC,因此不依赖于硬件平台。
它可以嵌入到廉价的微控制器中,如8051,PIC,AVR,SH,Z80,H8,ARM等等,不需要做任何修改。
FATFS源代码的获取,可以到官网下载;解压文件会得到两个文件夹,一个是doc文件夹,保存FATFS的一些使用文档和说明。
另一个是src文件夹,保存代码源文件。
FAT文件系统源码和sd卡读写的底层驱动。
2〕移植FAT文件系统只需根据硬件中可能接入的物理存储模块对文件系统的底层IO驱动〔diskio.c〕进展修改,具体需要修改的函数有:
DSTATUSdisk_initialize(BYTE);//存储介质的初始化
DSTATUSdisk_status(BYTE);//读取存储介质的状态
DRESULTdisk_read(BYTE,BYTE*,DWORD,BYTE);//读取数据
DRESULTdisk_write(BYTE,constBYTE*,DWORD,BYTE);//写入数据
DRESULTdisk_ioctl(BYTE,BYTE,void*);//读取存储介质文件系统相关信息
DWORDget_fattime(void);//返回文件系统的时间
3〕添加头文件、ff.h,增加SD卡的驱动号0如下:
/*Correspondencebetweenphysicaldrivenumberandphysicaldrive.*/
#defineSD_CARD0
#defineATA1
#defineMMC2
#defineUSB3
4〕diskio.c五个函数具体代码:
DSTATUSdisk_initialize(
BYTEdrv/*Physicaldrivenmuber(0..)*/
)
{
switch(drv)
{
卡
if(SD_Init()==SD_OK)
{
returnRES_OK;
}
else
{
returnRES_NOTRDY;
}
}
returnRES_NOTRDY;
}
//disk_ioctl和get_fattime两个函数暂时可以不实现直接返回
DRESULTdisk_ioctl(
BYTEdrv,/*Physicaldrivenmuber(0..)*/
BYTEctrl,/*Controlcode*/
void*buff/*Buffertosend/receivecontroldata*/
)
{
returnRES_NOTRDY;
}
#if!
_FS_READONLY
/*31-25:
Year(0-127org.1980),24-21:
Month(1-12),20-16:
Day(1-31)*/
/*15-11:
Hour(0-23),10-5:
Minute(0-59),4-0:
Second(0-29*2)*/
DWORDget_fattime(void)
{
return0;
}
#endif
5〕对于最底层〔物理层〕对SD卡的具体初始化和读写操作,STM32有SPI和SDIO两种方式实现,实际应用中根据硬件电路条件选择。
在没有SPI外设的单片机中也可以通过IO口模拟SPI协议。
〔具体实现代码略,详见工程文件中的sdio_sdcard.c和sdio_sdcard.h〕
6〕文件系统的测试应用。
在测试FAT文件系统之前,首先应该确保对底层SD卡的读写驱动正确。
所以第一步通过直接调用SD卡驱动函数实现对SD卡进展初始化检测和根本的读写操作,具体代码如下:
voidtest_SD()
{
SD_CardInfoSDCardInfo;
INT16Ui;
printf("SD卡驱动函数测试程序……\n\r");
while(SD_Init())//内存卡检测错误
{
printf("内存卡检测错误\n\r");
OSTimeDly(200);
}
printf("内存卡检测成功!
\n\r");
SD_GetCardInfo(&SDCardInfo);
printf("sdcardsizeis:
%u\n\r",SDCardInfo.CardCapacity>>22);
if(SD_ReadBlock(RxBuffer,0,512)==SD_OK)
{
for(i=0;i<512;i++)
{
printf("%X",RxBuffer[i]);
}
}
}
7〕如果上一步能初始化并检测出SD卡的大小,读出前512个字节的数据,那么说明SD卡和驱动函数都正常。
下一步设计一个FAT测试函数:
实现检测TEST.txt文件是否存在,存在那么读取文件中的前100个字节内容并串口输出;然后翻开TEST2.txt文件〔不存在那么创立〕写入读取到的内容〔没有内容那么写入“isnofileTEST.txt!
〞〕;翻开TEST2.txt读取文件中的前100个字节内容并串口输出。
具体代码如下。
voidtest_FAT()
{
FATFSfs;
FILf_1,f_2;
INT32Uread_count=21;
FRESULTerror;
error=f_mount(0,&fs);//挂载SD卡
error=f_open(&f_1,"TEST.txt",FA_OPEN_EXISTING|FA_READ);
if(error==FR_OK)
{
error=f_read(&f_1,RxBuffer,BUFFER_SIZE,&read_count);
printf("\n\rreadthefile:
TEST.txt\n\r");
printf("read100bytes,thenreturn%dbytes!
\n\r",read_count);
printf("thedatais:
\n\r");
printf((char*)RxBuffer);
error=f_close(&f_1);
}
error=f_open(&f_2,"TEST2.txt",FA_OPEN_ALWAYS|FA_WRITE);
printf("\n\rwritetest2.txt%dwords!
\n\r",read_count);
error=f_write(&f_2,RxBuffer,read_count,&read_count);
if(error==FR_OK)
{
printf("writeOK!
%dwordsarewrited~\n\r",read_count);
}else{
printf("writeerror\n\r");
}
error=f_close(&f_2);
error=f_open(&f_1,"TEST2.txt",FA_OPEN_EXISTING|FA_READ);
if(error==FR_OK)
{
error=f_read(&f_1,RxBuffer,BUFFER_SIZE,&read_count);
printf("\n\rreadthefile:
TEST2.txt\n\r");
printf("read100bytes,thenreturn%dbytes!
\n\r",read_count);
printf("thedatais:
\n\r");
printf((char*)RxBuffer);
error=f_close(&f_1);
}
}
“这是本任务的第xx次循环〞,然后在主函数中创立两个以上的该任务的线程〔这里需要注意实验三的资源冲突问题!
〕。
9〕具体代码,详见实例工程!
*扩展知识1:
在本工程中的SD底层驱动中,因为用32位存储SD卡的容量大小,所以最大只能识别到4GB,如果采用大于4G的卡进展测试那么读出的容量是错误的。
*扩展知识2:
对于FAT32的MBR区不一定是在0扇区中。
*扩展知识3:
〔可能是ffconf.h〕文件中_USE_STRFUNC宏定义为1,可以使用f_putc、f_puts、f_printf、f_