STM32开发环境建立实验报告

时间:2024.4.20

实验1 STM32开发环境建立

一、 实验目的

1、 掌握嵌入式开发环境的搭建。

2、 熟悉MINI STM32开发板的基本使用。

二、 实验内容

1、 检查MINI STM32开发板的完整性。

(1) ALIENTEK MINI STM32开发板底板一个。

(2) ALIENTEK 2.8寸 TFTLCD模块一个。

(3) 5P MINI USB 数据线一条。

2、 上电检测开发板能否正常工作,注意两个USB口的区别。

3、 串口驱动的安装。

4、 KEIL C软件的安装和使用。

5、 JLINK驱动的安装。

6、 跑马灯的实验。

三、 实验设备

硬件: PC机 一台

MINI STM32开发板 一套

软件: RVMDK V3.8 一套

Windows XP 一套

四、 实验步骤

1、 检查开发板完整、正常与否;

2、 安装开发软件及驱动,并调试;

3、 熟悉固件库,编写代码实现跑马灯功能。

1)给工程新增HARDWARE组

程序里main()函数非常简单,先调用delay_init()初始化延时,接着就是调用LED_Init()来初始化GPIOA和GPIOD为输出。最后在死循环里面实现LED0和LED1交替闪烁,间隔为300ms。 程序见附录

2) 写好程序以后,就编译,看看有没有错误。如果没有错误的话就下载到STM32板子上。

五、 实验结果和实验总结

实验最后实现了流水灯的运转。

这次实验主要是让我们了解一下STM32开发板的基本使用,大部分人都是初次接触这个开发板和KEILC软件,都对软件操作不太了解,希望通过这几次实验能够了解并熟练地使用这个软件,用这个软件来编程和完成一些功能的实现。

附录C语言代码:(主要功能的)

//初始化端口

void LED_Init(void)

{

RCC->APB2ENR|=1<<2; //使能PORTA时钟

RCC->APB2ENR|=1<<5; //使能PORTD时钟

GPIOA->CRH&=0XFFFFFFF0;

GPIOA->CRH|=0X00000003;//PA8 推挽输出

GPIOA->ODR|=1<<8; //PA8 输出高

GPIOD->CRL&=0XFFFFF0FF;

GPIOD->CRL|=0X00000300;//PD.2推挽输出

GPIOD->ODR|=1<<2; //PD.2输出高

}

//延时nms

void delay_ms(u16 nms)

{

u32 temp;

SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit) SysTick->VAL =0x00; //清空计数器

SysTick->CTRL=0x01 ; //开始倒数

do

{

temp=SysTick->CTRL;

}

while(temp&0x01&&!(temp&(1<<16)));//等待时间到达

SysTick->CTRL=0x00; //关闭计数器

SysTick->VAL =0X00; //清空计数器

}

//初始化延迟函数

//SYSTICK的时钟固定为HCLK时钟的1/8

//SYSCLK:系统时钟

void delay_init(u8 SYSCLK)

{

SysTick->CTRL&=0xfffffffb;//bit2清空,选择外部时钟 HCLK/8 fac_us=SYSCLK/8;

fac_ms=(u16)fac_us*1000;

}

//系统时钟初始化函数

void Stm32_Clock_Init(u8 PLL)

{

unsigned char temp=0;

MYRCC_DeInit(); //复位并配置向量表

RCC->CR|=0x00010000; //外部高速时钟使能HSEON

while(!(RCC->CR>>17));//等待外部时钟就绪

RCC->CFGR=0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1; PLL-=2;//抵消2个单位

RCC->CFGR|=PLL<<18; //设置PLL值 2~16

RCC->CFGR|=1<<16; //PLLSRC ON

FLASH->ACR|=0x32; //FLASH 2个延时周期

RCC->CR|=0x01000000; //PLLON

while(!(RCC->CR>>25));//等待PLL锁定

RCC->CFGR|=0x00000002;//PLL作为系统时钟

while(temp!=0x02) //等待PLL作为系统时钟设置成功 {

temp=RCC->CFGR>>2;

temp&=0x03;

}

}

//主函数

int main(void)

{

Stm32_Clock_Init(9); //系统时钟设置

delay_init(72); //延时初始化

LED_Init(); //初始化与LED连接的硬件接口 while(1)

{

LED0=0;

LED1=1;

delay_ms(300);

LED0=1;

LED1=0;

delay_ms(300);

}

}


第二篇:ARM实验报告


《嵌入式系统开发及应用》实验指导书

 2013 /  2014 年 第学期

姓名:        石荣荣     

学号:       10030221   

班级:       10计二      

指导教师:        钱诚        

计算机信息工程学院

计算机科学与工程系

20##年10月修订


目录

实验一、KEIL uVision 4集成开发环境实验................ 2

实验二、STM32F103XX流水灯实验......................... 2

实验三、EXTI中断模块实验.............................. 2

实验四、STM32F103XX定时器控制实验..................... 2

实验五、STM32F103XX彩屏显示实验....................... 2

实验六、电子时钟实验.................................. 2

实验七、看门狗模块实验................................ 2

实验八、触摸屏功能设计实验............................. 2


实验一、KEIL uVision 4集成开发环境实验

一、           实验目的

熟悉 KEIL uVision 4开发环境,学会JLINK-V8仿真器的使用。使用MDK编译、下载、调试并跟踪一段已有的程序,了解嵌入式开发的基本思想和过程。

二、           实验内容

本次实验使用KEIL uVision 4集成开发环境。新建一个简单的工程文件,并编译这个工程文件。学习 ARM 仿真器的使用和开发环境的设置。下载已经编译好的文件到嵌入式控制器中运行。学会在程序中设置断点,观察系统内存和变量,为调试应用程序打下基础。

三、           预备知识

C 语言的基础知识、程序调试的基础知识和方法。

四、           实验设备及工具

硬件:ARM 嵌入式开发平台、用于STM32F103RBT6的JLINK-V8仿真器、PC 机 Pentium100 以上。

软件:PC 机操作系统WinXP或者Windows 7、KEIL MDK420集成开发环境、仿真器驱动程序、超级终端通讯程序。

实验报告部分

一、   实验预习与准备:

1.   实验前预习了书本的1.2.1节关于Keil的相关内容;

2.   对以前学习的C语言进行了回顾、复习;

3.   学习了ARM程序的调试的相关知识。

二、   实验过程与结果,分析:

1.   实验在windows7平台下进行,打开Keil MDK开发环境,点击project,选择“new μvision project”;


图1-1、新建一个工程文件

2.   选择ARM芯片;

3.   添加源代码文件,选择菜单“File”-“New”,然后输入源代码即可;添加源文件到项目工程中时,除了添加源代码文件,还需要添加汇编格式的源代码、系统库文件,以及目标文件等;

图1-2、添加源文件到项目工程中

4.   编译程序代码,可以通过菜单、工具栏和浮动菜单等对代码进行编译;

5.   对源代码进行编译后,可以通过菜单的“Debug”-“Start/Stop Debug Session”或者“Ctrl+F5”进入调试状态;

6.   点击“Project”-“Build target”,再点击“Flash”-“Download”,就可以把程序烧录到STM32单片机中运行。

三、   实验小结与体会:

本次实验室考察对Keil这一开发环境的使用,由于课前查阅了相关资料,而且书上有相关说明,所以实验顺利完成,需要注意的是,在代码烧录前要选对芯片型号,导入源代码的时候记得导入相关的库文件、目标文件。

四、   教师评语:


实验二、STM32F103XX流水灯实验

一、        实验目的

1.   掌握STM32F103XX系列GPIO接口的使用;

2.   掌握GPIO引脚函数库的使用;

3.   熟悉uVision4开发环境;

4.   熟悉STM32F103XX程序调试。

二、        实验内容

初始化板上LED对应接口,根据已有外围LED硬件电路,设置引脚高低电平点亮、熄灭LED。设置延时控制灯点亮和熄灭时间,实现每次只点亮一个LED。并使得LED按序点亮、熄灭。

本次实验使用KEIL uVision 4集成开发环境。新建一个简单的工程文件,并编译这个工程文件。学习 ARM 仿真器的使用和开发环境的设置。下载已经编译好的文件到嵌入式控制器中运行。学会在程序中设置断点,观察系统内存和变量,为调试应用程序打下基础。

三、        预备知识

GPIO函数库操作知识、C 语言的基础知识、程序调试的基础知识和方法。

四、        实验设备及工具

硬件:ARM 嵌入式开发平台、用于STM32F103RBT6的JLINK-V8仿真器、PC 机 Pentium100 以上。

软件:PC 机操作系统WinXP或者Windows 7、KEIL MDK420集成开发环境、仿真器驱动程序、超级终端通讯程序。

实验报告部分

一、   实验预习与准备:

1.   查阅了STM32系列的GPIO引脚的功能描述;

2.   了解了STM32系列的GPIO寄存器的相关知识;

3.   学习了I/O口输入输出配置的功能;

二、         实验过程与结果,分析:

实验目的是让我把设置引脚的高低电平,达到让LED灯循环点亮的目的,期间可以自己设置延迟时间。实验代码主要分为LED初始化、main函数、系统时钟配置函数和延时函数。

代码如下:

1.   LED初始化函数。

void LED_Config(void){

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD , ENABLE);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;   //LED1  V6     

//将V6,V7,V8 配置为通用推挽输出 

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//口线翻转速度为50MHz

  GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_3; //LED2,LED3 V7 V8

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  GPIO_Init(GPIOD, &GPIO_InitStructure);

  GPIO_Init(GPIOD, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //LCD背光控制

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  GPIO_Init(GPIOD, &GPIO_InitStructure);

  GPIO_ResetBits(GPIOD, GPIO_Pin_13); //LCD背光关闭  

}

2.   主函数,通过设置LEDx的ON或OFF实现灯的点亮或熄灭

int main(void)

{

  RCC_Configuration();  //系统时钟配置

  LED_Config();        //LED控制配置

  while (1)

  {

    LED1_ON; LED2_OFF; LED3_OFF; //LED1亮  LED2,LED3灭

    Delay(0xAFFFF);

    LED1_OFF; LED2_ON; LED3_OFF; //LED2亮  LED1,LED3灭

    Delay(0xAFFFF);

    LED1_OFF; LED2_OFF; LED3_ON; //LED3亮  LED1,LED2灭

    Delay(0xAFFFF);   

  }

}

3.    系统时钟配置函数,将系统时钟设置为72MHZ

void RCC_Configuration(void)

{  

  SystemInit();

}

4.    Delay延时函数

void Delay(__IO uint32_t nCount)

{

   for(; nCount != 0; nCount--);

}

三、   实验小结与体会:

本次实验是实现LED等的循环点亮,通过控制引脚的高低电平达到实验目的,实验过程中delay函数不管怎么改,两个LED灯点亮的间隔都一样,上网查了相关资料才得以解决。在主函数中,通过让不同灯ON或者OFF可以控制灯的点亮顺序,总体来说本次实验较为成功,课后可以再对程序进行修改,以达到不同的效果。

四、   教师评语:


实验三、EXTI中断模块实验

一、        实验目的

1.    掌握STM32F103XX系列EXTI中断的原理;

2.    掌握STM32F103XX系列EXTI中断函数库的使用;

3.    掌握STM32F103XX中断向量的配置方法;

4.    熟悉uVision4开发环境;

5.    熟悉STM32F103XX程序调试。

二、        实验内容

设置两个按钮作为灯点亮、熄灭的控制开关。将按钮对应的引脚重映射为中断输入线,通过检测引脚上电平信号的下降沿控制LED1灯点亮。第二盏LED灯要求做中断上升沿检测,控制LED2灯熄灭。

本次实验使用KEIL uVision 4集成开发环境。新建一个简单的工程文件,并编译这个工程文件。学习 ARM 仿真器的使用和开发环境的设置。下载已经编译好的文件到嵌入式控制器中运行。学会在程序中设置断点,观察系统内存和变量,为调试应用程序打下基础。

三、        预备知识

EXTI库函数操作知识、C 语言的基础知识、程序调试的基础知识和方法。

四、        实验设备及工具

硬件:ARM 嵌入式开发平台、用于STM32F103RBT6的JLINK-V8仿真器、PC 机 Pentium100 以上。

软件:PC 机操作系统WinXP或者Windows 7、KEIL MDK420集成开发环境、仿真器驱动程序、超级终端通讯程序。

实验报告部分

一、   实验预习与准备:

1.   预习了EXIT中断的产生方式、基本原理;

2.   了解了下中断向量的配置方法;

3.   了解了下EXIT中断所具有的功能以及对应的GPIO口。

二、         实验过程与结果,分析:

实验要求实现用两个按钮控制对应的两个LED灯的点亮与熄灭,按钮K1,K2对应的LED灯为V6和V7,当按钮按下时产生一个下降沿,所以当按钮按下时灯被点亮。

代码如下:

1.   主函数

int main(void)

 unsigned char a=0,b=0;

  RCC_Configuration();         //系统时钟设置及外设时钟使能

  NVIC_Configuration();

  GPIO_Configuration();

  while (1)

  {numm();   //键盘扫描程序

    if(num==1&&a==0){GPIO_ResetBits(GPIOB, GPIO_Pin_5);a=1;}

    else if(num==1&&a==1){GPIO_SetBits(GPIOB, GPIO_Pin_5);a=0;}

    if(num==2&&b==0){GPIO_ResetBits(GPIOD, GPIO_Pin_6);b=1;}

    else if(num==2&&b==1){GPIO_SetBits(GPIOD, GPIO_Pin_6);b=0;}

  }

}

2.    键盘处理函数

void numm(void){

  num=0;

  if(_it0==1){                          //按键按下标志

   if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)==0){//K1 

      Delay(0x3ffff);   

         if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)==0){    //按键消抖动

             while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)==0);

             num=1;        //键值1  为K1按下

             goto n_exit;

         }

      }

   }

 else if(_it0==2){  //按键按下标志

    if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2)==0){//K2 

      Delay(0x3ffff);                                             

         if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2)==0){//按键消抖动

             while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2)==0);

             num=2;             //键值2  为K2按下

             goto n_exit;

         }

      } 

   } 

   n_exit:;

   _it0=0; }

3.    LED控制口线及键盘设置

void GPIO_Configuration(void)

{ GPIO_InitTypeDef GPIO_InitStructure;

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;   //LED1  V6

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOB, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;   //LED2 V7

  GPIO_Init(GPIOD, &GPIO_InitStructure);

  GPIO_SetBits(GPIOB, GPIO_Pin_5);           //LED1 亮

  GPIO_SetBits(GPIOD, GPIO_Pin_6);            //LED2 亮

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;    //输入上拉

  GPIO_Init(GPIOC, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;    //输入上拉

  GPIO_Init(GPIOC, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;            //LCD背光控制

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  GPIO_Init(GPIOD, &GPIO_InitStructure);

  GPIO_ResetBits(GPIOD, GPIO_Pin_13);                 //LCD背光关闭 

}

4.    中断源配置函数

void NVIC_Configuration(void)

{ NVIC_InitTypeDef NVIC_InitStructure;

  EXTI_InitTypeDef EXTI_InitStructure;

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  NVIC_InitStructure.NVIC_IRQChannel =EXTI9_5_IRQn; //外部中断9-5

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 0

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级1 

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  //使能

  NVIC_Init(&NVIC_InitStructure);

  NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //外部中断2

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 0

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;   //子优先级2 

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  //使能

  NVIC_Init(&NVIC_InitStructure);

  GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource5);   

  GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource2);  

  EXTI_InitStructure.EXTI_Line = EXTI_Line5;  //PC5 作为键盘K1 检测状态

  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;    //中断模式

  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;   //下降沿触发

  EXTI_InitStructure.EXTI_LineCmd = ENABLE;

  EXTI_Init(&EXTI_InitStructure);

  EXTI_InitStructure.EXTI_Line = EXTI_Line2;  //PC2 作为键盘K2 检测状态

  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;       //中断模式

  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;   //下降沿触发

  EXTI_InitStructure.EXTI_LineCmd = ENABLE;

  EXTI_Init(&EXTI_InitStructure);

}

实验结果:当按下按钮时,产生一个下降沿触发,产生中断,点亮LED灯,再次按下的时候又产生一个中断,熄灭LED。

三、   实验小结与体会:

本次实验是通过实现按键点亮LED灯,达到学习EXIT中断的目的。实验主要是对中断源进行配置,设置中断优先级;键盘处理函数方面,要注意对按键按下进行消抖;在LED控制和键盘设置函数中,对按键进行初始化和上拉设置。实验还有一些地方不够完善,但基本实现了实验要求,课后还可以对其进行修改,对于实验按键按下LED点亮,松开则熄灭这一效果无法实现,还应该查询相关资料或请教老师。通过实验学到了很多,比如电位上升或下降可以产生一个中断源;如何设置中断优先级;如何进行输入上拉和下拉的设置等。

四、   教师评语:


实验四、STM32F103XX定时器控制实验

一、        实验目的

1.    掌握STM32F103XX系列定时器工作原理;

2.    掌握STM32F103XX系列定时器的设置;

3.    掌握GPIO引脚函数库的使用;

4.    熟悉uVision4开发环境;

5.    熟悉STM32F103XX程序调试。

二、        实验内容

正确设置STM32F103XX高级定时器TIM1,控制外部LED1灯定时点亮。通过正确设置预分频系数、计数模式以及计数值,使得定时时长分别为1秒,0.01秒。

本次实验使用KEIL uVision 4集成开发环境。新建一个简单的工程文件,并编译这个工程文件。学习 ARM 仿真器的使用和开发环境的设置。下载已经编译好的文件到嵌入式控制器中运行。学会在程序中设置断点,观察系统内存和变量,为调试应用程序打下基础。

三、        预备知识

GPIO函数库操作知识、C 语言的基础知识、程序调试的基础知识和方法。

四、        实验设备及工具

硬件:ARM 嵌入式开发平台、用于STM32F103RBT6的JLINK-V8仿真器、PC 机 Pentium100 以上。

软件:PC 机操作系统WinXP或者Windows 7、KEIL MDK420集成开发环境、仿真器驱动程序、超级终端通讯程序。

实验报告部分

一、   实验预习与准备:

1.   学习了如何查询固件库内TIM定时器相关信息;

2.   了解了TIM的工作方式以及结构特征;

3.   学习了GPIO引脚函数库的使用。

二、         实验过程与结果,分析:

实验过程相对简单,主要是对TIM1定时器进行相关设置,使LED1能够定时点亮与熄灭,其中TIM1定时器使用了向上技术模式,通过修改Tim.c文件中的TIM1_TimeBaseStructure.TIM_Period 后面的值,可以控制灯以1s或0.1s时间闪亮,其中分频系数设置为20000。

代码如下:

1.   主函数:

int main(void)

{   

RCC_Configuration();           //系统时钟设置及外设时钟使能

NVIC_Configuration();          //中断源配置

time_ini();                    //定时器1的初始化

while(1);

}

2.   中断源配置

void NVIC_Configuration(void)

{

 NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

NVIC_InitStructure.NVIC_IRQChannel =TIM1_UP_IRQn ;//配置定时器中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);     

}

3.   TIM1初始化函数

void time_ini(void){

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//定时器1 时钟使能

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA9复用为TIM1的通道2

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

TIM1_TimeBaseStructure.TIM_Prescaler = 20000;          //预分频器TIM1   

TIM1_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式

TIM1_TimeBaseStructure.TIM_Period =3600;      //自动重装载寄存器        

TIM1_TimeBaseStructure.TIM_ClockDivision = 0x0;    //时钟分频因子

TIM_TimeBaseInit(TIM1,&TIM1_TimeBaseStructure);    //写TIM1 各寄存器参数

TIM_Cmd(TIM1,ENABLE);           //启动定时器1

TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE); // 允许捕获/比较2中断

}

实验主要是对TIM1进行分频系数的设置,选用PA9口来作为TIM1的通道。由于0.01s的闪烁看上去像LED一直亮着,所以这里改成了0.1s闪烁。


三、   实验小结与体会:

本次实验过程中有很多错误,比较难解决的就是LED等不亮,后来虽然亮了但是无法进入中断,也就是说LED不闪。后来询问同学才得以解决,不闪的原因是TIM1定时器没有使能,而且复用通道没有选对,查询开发板原理图,选择了PA9口,LED亮了,然后是闪烁问题,是因为分频系数设置错误,还有自动重装载寄存器数值不对,通过修改也得到了解决。实验涉及到了很多关于TIM1定时器的知识,虽然还没有熟练掌握,但是也学到了很多,相信多加练习以后能够更好地使用定时器来实现各种效果。

四、   教师评语:


实验五、STM32F103XX彩屏显示实验

一、        实验目的

1.    掌握TFT彩屏显示原理;

2.    掌握ILI9320控制器的设置;

3.    掌握GPIO引脚函数库的使用;

4.    熟悉uVision4开发环境;

5.    熟悉STM32F103XX程序调试。

二、        实验内容

确定STM32F103XX控制器与TFT座之间的硬件连线。通过写LCD片选信号使能LCD,由读写信号WR、RD控制对LCD的操作。完成屏幕上的文字输出,并可设置文字颜色、字体大小等属性。绘制矩形框包围住该文字。

本次实验使用KEIL uVision 4集成开发环境。新建一个简单的工程文件,并编译这个工程文件。学习 ARM 仿真器的使用和开发环境的设置。下载已经编译好的文件到嵌入式控制器中运行。学会在程序中设置断点,观察系统内存和变量,为调试应用程序打下基础。

三、        预备知识

GPIO函数库操作知识、C 语言的基础知识、程序调试的基础知识和方法。

四、        实验设备及工具

硬件:ARM 嵌入式开发平台、用于STM32F103RBT6的JLINK-V8仿真器、PC 机 Pentium100 以上。

软件:PC 机操作系统WinXP或者Windows 7、KEIL MDK420集成开发环境、仿真器驱动程序、超级终端通讯程序。

实验报告部分

一、   实验预习与准备:

1.   了解了TFT显示屏的工作原理;

2.   查阅了开发板上TFT屏幕的相关资料参数;

3.   学习了GPIO引脚库的使用;

4.   奋斗版STM32开发板和KEIL MDK开发环境。

二、   实验过程与结果,分析:

LCD显示原理:

LCD显示器是通过给不同的液晶单元供电,控制其光线的通过与否,从而达到显示的目的。因此,LCD的驱动控制归于对每个液晶单元通断电的控制,每个液晶单元都对应着一个电极,对其通电,便可使用光线通过(也有刚好相反的,即不通电时光线通过,通电时光线不通过)。光源的提供方式有两种:透射式和反射式。笔记本电脑的LCD显示屏即为透射式,屏后面有一个光源,因此外界环境可以不需要光源。而一般微控制器上使用的LCD为反射式,需要外界提供光源,靠反射光来工作。

实验过程中不要先写屏,要先读ID,确认驱动IC是否正确,烧录开发板之前要先确认串口是否设置正确。

代码如下:

1.   LCD写字子程序:

void lcd_wr_zf(u16 StartX, u16 StartY, u16 X, u16 Y, u16 Color, u8 Dir, u8 *chr)

{   unsigned int temp=0,num,R_dis_mem=0,Size=0,x=0,y=0,i=0;

    if(Dir==2) LCD_WR_CMD(0x0003,0x1010);  

    else if(Dir==3) LCD_WR_CMD(0x0003,0x1028);  

    if(Dir==0){

         LCD_WR_CMD(0x0003,0x1030);

         LCD_WR_CMD(0x0210, StartX);      //水平显示区起始地址 0-239

         LCD_WR_CMD(0x0211, StartX+X-1);  //水平显示区结束地址 0-239

         LCD_WR_CMD(0x0212, StartY);      //垂直显示区起始地址 0-399

         LCD_WR_CMD(0x0213, StartY+Y-1);  //垂直显示区结束地址 0-399

         LCD_WR_CMD(0x0200, StartX);     //水平显示区地址

         LCD_WR_CMD(0x0201, StartY);      //垂直显示区地址 

         LCD_WR_REG(0x0202);               /准备写数据显示区

         Size=X*Y;                        //字符串或字符占用的像素尺寸

         while(i<Size){

             temp=*chr++;

             for(num=0; num<8; num++){   //数组的每个字节代表了8个像素      

                  if((temp&0x80)>0){

                       LCD_WR_Data(Color);

                  }

                  else{

                       LCD_WR_CMD(0x0200, StartX+x);//水平显示区地址

                       LCD_WR_CMD(0x0201, StartY+y);//垂直显示区地址

                       LCD_WR_REG(0x0202);         //准备读数据显示区

                                 R_dis_mem=LCD_RD_data();             LCD_WR_Data(R_dis_mem);

                  }

                  temp=temp<<1;            //字节各位的移出

                  x++;

                  if(x>=X){x=0; y++;}

                  i++;

             }

         }

    }

    else if(Dir==1){

         LCD_WR_CMD(0x0003,0x1018);

         LCD_WR_CMD(0x0210, StartY);           //水平显示区起始地址 0-239

         LCD_WR_CMD(0x0211, StartY+Y-1);      //水平显示区结束地址 0-239

         LCD_WR_CMD(0x0212, 399-(StartX+X-1)); //垂直显示区起始地址 0-399

         LCD_WR_CMD(0x0213, 399-StartX);      //垂直显示区结束地址 0-399

         LCD_WR_CMD(0x0200, StartY);            //水平显示区地址

         LCD_WR_CMD(0x0201, 399-StartX);       //垂直显示区地址 

         LCD_WR_REG(0x0202);                   //准备写数据显示区

         Size=X*Y;                             //字符串或字符占用的像素尺寸

         while(i<Size){

             temp=*chr++;

             for(num=0; num<8; num++){     //数组的每个字节代表了8个像素

                  if((temp&0x80)>0){

                       LCD_WR_Data(Color);

                  }

                  else{

                       LCD_WR_CMD(0x0200, StartY+y);//水平显示区地址

                       LCD_WR_CMD(0x0201, 399-(StartX+x));//垂直显示区地址

                       LCD_WR_REG(0x0202);    //准备读数据显示区

                                 R_dis_mem=LCD_RD_data();                  LCD_WR_Data(R_dis_mem);

                  }

                  temp=temp<<1; //字节各位的移出

                  x++;

                  if(x>=X){x=0; y++;}

                  i++;

             }

         }

    }

}

void LCD_test(void)

{unsigned char *p;    

p=num_pub(10);

lcd_wr_zf(74,30,24,32,color1,1,p);

lcd_wr_zf(146,30,24,32,color1,1,p);

    p=num_pub(t2);

    lcd_wr_zf(26,30,24,32,color1,1,p);

    p=num_pub(t1);

    lcd_wr_zf(50,30,24,32,color1,1,p); 

    p=num_pub(f2);

    lcd_wr_zf(98,30,24,32,color1,1,p); 

    p=num_pub(f1);

    lcd_wr_zf(122,30,24,32,color1,1,p); 

    lcd_DrawPicture(170,30,1,a3);

    p=num_pub(m2);

    lcd_wr_zf(170,30,24,32,color1,1,p); 

    lcd_DrawPicture(194,30,1,a3);

    p=num_pub(m1);

    lcd_wr_zf(194,30,24,32,color1,1,p); 

    color1++;

    if(color1>=65536) color1=0; 

    Delay(0xafffff);

    m1=TSS%10;

    m2=TSS/10;

    f1=TMM%10;

    f2=TMM/10;

    t1=THH%10;

    t2=THH/10;

    lcd_DrawPicture(98,30,1,a3);

    lcd_DrawPicture(122,30,1,a3);

    lcd_DrawPicture(50,30,1,a3);

    lcd_DrawPicture(26,30,1,a3);

}

unsigned char *num_pub(unsigned  int a){

    unsigned char *b;

    switch(a){

         case 1: b=&zm1[0]; break;

         case 2: b=&zm2[0]; break;

         case 3: b=&zm3[0]; break;

         case 4: b=&zm4[0]; break;

         case 5: b=&zm5[0]; break;

         case 6: b=&zm6[0]; break;

         case 7: b=&zm7[0]; break;

         case 8: b=&zm8[0]; break;

         case 9: b=&zm9[0]; break;

         case 10: b=&zm10[0]; break;

         case 0: b=&zm0[0]; break;

         default: b=&zm0[0];break;

    }

    return(b);

}

2.   在指定位置显示图片背景

void lcd_DrawPicture(u16 StartX,u16 StartY,u8 Dir,u8 *pic)

{

  u32  i=8, len;

  u16 temp,x,y;

  x=((uint16_t)(pic[2]<<8)+pic[3])-1;         //从图像数组里取出图像的长度

  y=((uint16_t)(pic[4]<<8)+pic[5])-1;         //从图像数组里取出图像的高度

  if(Dir==0){

    LCD_WR_CMD(0x0003,0x1030);   //图像显示方向为左下起行递增列递减

    LCD_WR_CMD(0x0210, StartX);      //水平显示区起始地址 0-239

    LCD_WR_CMD(0x0211, StartX+x);         //水平显示区结束地址 0-239

    LCD_WR_CMD(0x0212, StartY);          //垂直显示区起始地址 0-399

    LCD_WR_CMD(0x0213, StartY+y);        //垂直显示区结束地址 0-399

    LCD_WR_CMD(0x0200, StartX);          //水平显示区地址

    LCD_WR_CMD(0x0201, StartY);          //垂直显示区地址

  }

  else if(Dir==1){

    LCD_WR_CMD(0x0003,0x1018);       //图像显示方向为左下起  行递增  列递减

    LCD_WR_CMD(0x0210, StartY);               //水平显示区起始地址 0-239

    LCD_WR_CMD(0x0211, StartY+y);           //水平显示区结束地址 0-239

    LCD_WR_CMD(0x0212, 399-(x+StartX));     //垂直显示区起始地址 0-399

    LCD_WR_CMD(0x0213, 399-StartX);         //垂直显示区结束地址 0-399

    LCD_WR_CMD(0x200, StartY);               //水平显示区地址

    LCD_WR_CMD(0x201, 399-StartX);          //垂直显示区地址

  }

  LCD_WR_REG(0x0202);                              //写数据到显示区

  len=2*((uint16_t)(pic[2]<<8)+pic[3])*((uint16_t)(pic[4]<<8)+pic[5]);    while(i<(len+8)) {                            //从图像数组的第9位开始递增

    temp=(uint16_t)( pic[i]<<8)+pic[i+1];

    LCD_WR_Data(temp); //将取出的16位像素数据送入显示区

    i=i+2;                 //取模位置加2,以为获取下一个像素数据

  }

}

void LCD_WR_REG(unsigned int index) //写寄存器地址函数

{*(__IO uint16_t *) (Bank1_LCD_C)= index; 

}

void LCD_WR_CMD(unsigned int index,unsigned int val) //写寄存器数据函数

{  

    *(__IO uint16_t *) (Bank1_LCD_C)= index; 

    *(__IO uint16_t *) (Bank1_LCD_D)= val;

}

unsigned int LCD_RD_data(void){ //读显示地址数据

    unsigned int a=0;

    a=*(__IO uint16_t *) (Bank1_LCD_D);   //空操作

    a=*(__IO uint16_t *) (Bank1_LCD_D);   //读出的实际16位像素数据   

    return(a);

}

实验结果是将时钟显示在LCD显示屏上,背景为白色,由于这个实验和下一个时钟实验都需要将字符显示在显示屏上,所以连在一起做,屏幕的时分秒以绿颜色显示在屏幕左上角。

三、   实验小结与体会:

本次实验主要是学习了LCD的使用,学会了如何使文字显示在显示屏上,了解了ILI9320控制器的设置和先关GPIO引脚的使用。开始时代码无法烧录到开发板中,后来设置了串口参数得以解决,这次实验给我的感觉就是,LCD的初始化设置不用太过注意,但是LCD驱动要检查是否正确,还有就是串口要设置正确。

四、   教师评语:


实验六、电子时钟实验

一、        实验目的

1.   掌握RTC实时时钟的工作原理;

2.   掌握RTC实时时钟的设置;

3.   掌握中断向量的设置;

4.   熟悉uVision4开发环境;

5.   熟悉STM32F103XX程序调试。

二、        实验内容

根据RTC开发一个可显示当前时间的电子时钟,要求时钟在显示屏上显示时包括时、分、秒。每一秒钟都要求更新秒数的显示,当计满秒数,更新分数,当计满分数,更新时数。

本次实验使用KEIL uVision 4集成开发环境。新建一个简单的工程文件,并编译这个工程文件。学习 ARM 仿真器的使用和开发环境的设置。下载已经编译好的文件到嵌入式控制器中运行。学会在程序中设置断点,观察系统内存和变量,为调试应用程序打下基础。

三、        预备知识

GPIO函数库操作知识、C 语言的基础知识、程序调试的基础知识和方法。

四、        实验设备及工具

硬件:ARM 嵌入式开发平台、用于STM32F103RBT6的JLINK-V8仿真器、PC 机 Pentium100 以上。

软件:PC 机操作系统WinXP或者Windows 7、KEIL MDK420集成开发环境、仿真器驱动程序、超级终端通讯程序。

实验报告部分

一、   实验预习与准备:

1.   学习了RTC时钟的相关知识,了解了其工作原理、功能特性、内部结构;

2.   查阅了书上关于RTC时钟相关设置的资料;

3.   奋斗版STM32开发板和KEIL MDK开发环境。

二、   实验过程与结果,分析:

实验中的显示效果由上个实验实现,本次实验的电子时钟主要使用RTC寄存器来完成,RTC模块具有一个可以连续计数的计数器,而其本身是一个独立的寄存器。

实验结果为,将程序烧入开发板之后,显示屏开始从0时0分0秒显示实践,每次增加1秒。

代码如下:

1.   RTC初始化函数:

void RTC_Configuration(void)

{

    PWR_BackupAccessCmd(ENABLE);

    BKP_DeInit();

    #ifdef RTCClockSource_LSI

         RCC_LSTCmd(ENABLE);

         while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);

         RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);

    #elif defined RTCClockSource_LSE

         RCC_LSEConfig(RCC_LSE_ON);

         while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);

         RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

    #endif

    RCC_RTCCLKCmd(ENABLE);

    #ifdef RTCClockOutput_Enable 

    /* Disable the Tamper Pin */

    BKP_TamperPinCmd(DISABLE); /* To output RTCCLK/64 on Tamper pin, the tamper

                               functionality must be disabled */                        

    BKP_RTCCalibrationClockOutputCmd(ENABLE);/* 使能在TAMPER脚输出RTC时钟 */

    #endif

    RTC_WaitForSynchro();

    RTC_WaitForLastTask();

    RTC_ITConfig(RTC_IT_SEC, ENABLE);

    RTC_WaitForLastTask();

    #ifdef RTCClockSource_LSI

    RTC_SetPrescaler(31999);/* RTC period = RTCCLK/RTC_PR = (32.000 KHz)/(31999+1) */

    #elif defined RTCClockSource_LSE

    RTC_SetPrescaler(32767);/* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */

    #endif

    RTC_WaitForLastTask();

}

2.   时间调整函数:

u32 Time_Regulate(void)

{ u32 Tmp_HH = 0xFF, Tmp_MM = 0xFF, Tmp_SS = 0xFF;

  printf("\r\n==============Time Settings=====================================");

  printf("\r\n  Please Set Hours");

  while(Tmp_HH == 0xFF)                       

  {Tmp_HH = USART_Scanf(23);   //从串口获取小时数据

  }

  printf(":  %d", Tmp_HH);

  printf("\r\n  Please Set Minutes");

  while(Tmp_MM == 0xFF)

  {Tmp_MM = USART_Scanf(59);  //从窗口获取分钟数据

  }

  printf(":  %d", Tmp_MM);

  printf("\r\n  Please Set Seconds");

  while(Tmp_SS == 0xFF)

  {Tmp_SS = USART_Scanf(59);   //从串口获取秒数据

  }

  printf(":  %d", Tmp_SS);

  return((Tmp_HH*3600 + Tmp_MM*60 + Tmp_SS)); /* 返回保存在计数寄存器里的值 */

}

3.   中断源配置函数:

void NVIC_Configuration(void)

{   NVIC_InitTypeDef NVIC_InitStructure;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; //配置外部中断源(秒中断)

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

}

4.   实时时钟初始化函数:

void Clock_ini(void)

{

    if(BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)

    {   printf("\r\n RTC not yet configured....");

        RTC_Configuration();

        printf("\r\n RTC configured....");

RTC_WaitForLastTask();/* 等待写RTC寄存器完成 */

         RTC_SetCounter(Time_Regulate()); /* 改变当前时间 */

         RTC_WaitForLastTask();      /* 等待写RTC寄存器完成 */

         BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);

    }

    else

    {   if(RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET) //检查是否掉电重启

         {printf("\r\n\n Power On Reset occurred....");    

         }

         else if(RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET) //检查是否复位

         {printf("\r\n\n External Reset occurred....");

         }

         printf("\r\n No need to configure RTC....");

         RTC_WaitForSynchro();  //等待RTC寄存器被同步

         RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能秒中断

         RTC_WaitForLastTask(); //等待写入完成

    }

    RCC_ClearFlag();

}

三、   实验小结与体会:

通过本次实验我学习到了很多RTC实时时钟的知识,RTC的驱动时钟是由外部晶振提供的。实验原理是将时钟数据写入到RTC寄存器,保存在寄存器中,然后RTC寄存器中的时间数据会根据RTC时钟自动进行计数操作。但是因为没有保持系统至少有一个电源对其供电,所以时钟数据每次都是从0时0分0秒开始,对本次实验课后还可以加以修改完善。通过本次实验对于RTC模块的学习还不够深入,还应多加动手实践,深入学习。

四、   教师评语:


实验七、看门狗模块实验

一、        实验目的

1.    掌握独立看门狗和窗口看门狗工作原理;

2.    掌握看门狗寄存器的配置;

3.    掌握中断的配置;

4.    掌握GPIO引脚函数库的使用;

5.    熟悉uVision4开发环境;

6.    熟悉STM32F103XX程序调试。

二、        实验内容

使用按键模拟重启开关,分别使用独立看门狗与窗口看门狗实现100ms的定时复位,通过定时中断或提早唤醒中断进行“喂狗”操作防止复位中断的产生。按键按下触发EXTI中断,在中断服务程序设置延迟,从而使得复位中断产生。其中LED灯常亮表示程序正常运行状态。

本次实验使用KEIL uVision 4集成开发环境。新建一个简单的工程文件,并编译这个工程文件。学习 ARM 仿真器的使用和开发环境的设置。下载已经编译好的文件到嵌入式控制器中运行。学会在程序中设置断点,观察系统内存和变量,为调试应用程序打下基础。

三、        预备知识

GPIO函数库操作知识、C 语言的基础知识、程序调试的基础知识和方法。

四、        实验设备及工具

硬件:ARM 嵌入式开发平台、用于STM32F103RBT6的JLINK-V8仿真器、PC 机 Pentium100 以上。

软件:PC 机操作系统WinXP或者Windows 7、KEIL MDK420集成开发环境、仿真器驱动程序、超级终端通讯程序。

实验报告部分

一、   实验预习与准备:

1.   预习书本上看门狗的工作原理;

2.   了解了独立看门狗和窗口看门狗的作用;

3.   了解了下GPIO引脚函数库的内容。

二、   实验过程与结果,分析:

实验通过使用STM32的两个看门狗实现100ms的定时复位,当按键按下时会产生一个复位中断,并且LED灯亮,使得系统复位,相当于重启。对于窗口看门狗在系统运行期间,应当周期性地向WWDG_CR寄存器写入新的数值,防止复位中断的产生。

代码如下:

1.   主函数:

int main(void)

{

RCC_Configuration();

GPIO_Configuration();

if(RCC_GetFlagStatus(RCC_FLAG_WWDGRST) != RESET)

{GPIO_WriteBit(GPIOC, GPIO_Pin_6, Bit_SET);

RCC_ClearFlag();

}

  else

  {GPIO_WriteBit(GPIOC, GPIO_Pin_6, Bit_RESET);

  }

  EXTI_Configuration();

  NVIC_Configuration();

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);

  WWDG_SetPrescaler(WWDG_Prescaler_8);

  WWDG_SetWindowValue(0x41);

  /* Enable WWDG and set counter value to 0x7F,  0x7f-0x41=64 --WWDG timeout = ~4 ms * 64 = 262 ms */

  WWDG_Enable(0x7F);

  WWDG_ClearFlag();/* Clear EWI flag */

  WWDG_EnableIT();/* Enable EW interrupt */

  while (1)

  {

  }

}

2.   中断源配置函数:

void NVIC_Configuration(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

  /* 2 bits for Preemption Priority and  2 bits for Sub Priority */

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

  NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

  NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQChannel;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

  NVIC_Init(&NVIC_InitStructure);

}

3.   EXTI初始化函数:

void EXTI_Configuration(void)

{

  EXTI_InitTypeDef EXTI_InitStructure;

  /* Connect EXTI Line9 to PB.9 */

  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource9);

  /* Configure EXTI Line9 to generate an interrupt on falling edge */

  EXTI_ClearITPendingBit(EXTI_Line9);

  EXTI_InitStructure.EXTI_Line = EXTI_Line9;

  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿有效

  EXTI_InitStructure.EXTI_LineCmd = ENABLE;

  EXTI_Init(&EXTI_InitStructure);

}

4.   看门狗中断响应函数:

void WWDG_IRQHandler(void)

{  WWDG_SetCounter(0x7F)

  WWDG_ClearFlag();

  GPIO_WriteBit(GPIOC, GPIO_Pin_7, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_7)));

三、   实验小结与体会:

本次实验主要让我们学习如何使用看门狗来让系统稳定,安全地运行,看门狗的原理是当看门狗计数器达到一个给定的数值时,触发中断或者系统复位。本次实验通过按键按下产生一个中断,由于中断服务延迟,使得“喂狗”操作停止,这时候看门狗便会产生系统复位,达到重启的效果。实验虽然完成了,但是对于看门狗的设置与使用还不是完全掌握,还需要多加钻研学习。

四、   教师评语:


实验八、触摸屏功能设计实验

一、        实验目的

1.    掌握触摸屏工作原理;

2.    掌握显示屏图形绘制函数的使用;

3.    掌握定时器的配置;

4.    掌握GPIO引脚函数库的使用;

5.    熟悉uVision4开发环境;

6.    熟悉STM32F103XX程序调试。

二、        实验内容

绘制一个矩形框,在普通模式下线色为黑色,当用户接触屏幕时,检测触点位置,并判断触点是否在矩形框内部,如果触点在矩形框内部,矩形框线色改变,在触点移动时,矩形框随之移动。

本次实验使用KEIL uVision 4集成开发环境。新建一个简单的工程文件,并编译这个工程文件。学习 ARM 仿真器的使用和开发环境的设置。下载已经编译好的文件到嵌入式控制器中运行。学会在程序中设置断点,观察系统内存和变量,为调试应用程序打下基础。

三、        预备知识

GPIO函数库操作知识、C 语言的基础知识、程序调试的基础知识和方法。

四、        实验设备及工具

硬件:ARM 嵌入式开发平台、用于STM32F103RBT6的JLINK-V8仿真器、PC 机 Pentium100 以上。

软件:PC 机操作系统WinXP或者Windows 7、KEIL MDK420集成开发环境、仿真器驱动程序、超级终端通讯程序。

实验报告部分

一、     实验预习与准备:

1.   预习了触摸屏的相关知识,了解了其基本的工作原理;

2.   学习如何使用显示屏绘图函数;

3.   了解如何配置定时器和GPIO引脚。

二、     实验过程与结果,分析:

实验结果是当你触摸屏幕上的矩形框内时,矩形框颜色改变;当你触摸屏幕其他地方时,矩形框会出现在你触摸的地方。实验原理其实就是判断你触摸点屏幕的位置,当该位置在矩形框内时,系统进行清屏操作,然后在相同的位置用不同的颜色重画该矩形框,当你的触摸坐标不在框内时,系统也进行清屏操作,然后在触摸的坐标位置重画矩形框。

代码如下:

1.         主函数:

int main(void)

{ unsigned short a;

  RCC_Configuration();            //系统时钟初始化及端口外设时钟使能

  GPIO_Configuration();                //状态LED1的初始化

  tp_Config();                         //SPI1 触摸电路初始化       

  FSMC_LCD_Init();                     //FSMC TFT接口初始化

  LCD_Init();                          //LCD初始化代码

  TFT_CLEAR(0,0,240,400);          //清屏   

  if (SysTick_Config(720))        //时钟节拍中断时10us一次  用于定时

  {

    while (1);

  } 

  TFT_ShowString(80,60,"Touch screen");   //用于第一个触摸屏校正的提示

  for(a=0; a<10; a++){         //在竖屏模式下,左上角显示第一个校正点点击区域

   drawbigpoint(0,0+a);

   drawbigpoint(a,0);

  }    

  while (1)                    //等待点击第一个触摸校正点

  {   

    if(PEN==0){                //点击第一个校正点 等待触摸检测电平变低

        Delay_us(34000);            //延时340ms 消除抖动

        if(PEN==0){                 //检测触摸中断线是否可靠点击

             while(PEN==0){         //点击未松开,持续读取触摸坐标

                 Delay_us(1);

                 Read_XPT2046();    //读取触摸坐标

                 Xs=X; Ys=Y;   //获得第一个校正点的X,Y  

                 Delay_us(34000);   //延时340ms 消除抖动       

             }

             break;  

        }   

    }  

  }

  TFT_CLEAR(0,0,240,400);                      //清屏  

  TFT_ShowString(80,60,"Touch Second Point");     //用于第二个触摸屏校正的提示    

  for(a=0; a<20; a++){              //在竖屏模式下,左上角显示第二个校正点点击区域

   drawbigpoint(120,190+a);

   drawbigpoint(110+a,200);

  }       

  while (1)                  //等待点击第二个触摸校正点

  {                               

   if(PEN==0){           //点击第二个校正点 等待触摸检测电平变低

         Delay_us(34000);            //延时340ms 消除抖动

         if(PEN==0){            //检测触摸中断线是否可靠点击

             while(PEN==0){         //点击未松开,持续读取触摸坐标

                 Delay_us(1);

                  Read_XPT2046();    //读取触摸坐标

                  Xe=X; Ye=Y;        //获得第二个校正点的X,Y

                  Delay_us(34000);   //延时340ms 消除抖动

             }

             break;

         }   

     }  

  }

  X2=Xe-Xs; X2=X2/120; 

  Y2=Ye-Ys; Y2=Y2/200; 

  dw=1;           //校正完成标志

  POINT_COLOR=RED; //文字显示的颜色默认值

  TFT_CLEAR(0,0,240,400); //清屏    

  TFT_ShowString(220,0,"CLR");

  while (1)    //等待中断到来

  {  

    if(PEN==0){

         Delay_us(5000);        //延时50ms用于触笔消抖

         while(PEN==0){         //未抬起触笔的情况下画图

             Read_XPT2046();

         }

    }

  }     

}

2.         TFT初始化函数:

void tp_Config(void)

{

  GPIO_InitTypeDef  GPIO_InitStructure;

  SPI_InitTypeDef   SPI_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;             //口线速度50MHZ

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;         //复用模式

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;             //口线速度50MHZ

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;     //推挽输出模式

  GPIO_Init(GPIOB, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;      //SPI1 SST25VF016B片选

  GPIO_Init(GPIOC, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;     //SPI1 VS1003片选

  GPIO_Init(GPIOB, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;      //SPI1 网络模块片选

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_SetBits(GPIOC, GPIO_Pin_4);       //SPI CS1

  GPIO_SetBits(GPIOB, GPIO_Pin_12);      //SPI CS4

  GPIO_SetBits(GPIOA, GPIO_Pin_4);       //SPI NSS   

  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;   //全双工 

  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;   //主模式

  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;    //8位

  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //时钟极性 空闲状态时,SCK保持低电平

  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //时钟相位 数据采样从第一个时钟边沿开始

  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //软件产生NSS

  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;

  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;   //数据高位在前

  SPI_InitStructure.SPI_CRCPolynomial = 7;   //CRC多项式寄存器初始值为7

  SPI_Init(SPI1, &SPI_InitStructure);

  SPI_Cmd(SPI1,ENABLE); 

}

3.         X,Y轴数据读出函数:

u16 TPReadX(void)

{

   u16 x=0;

   TP_CS();                          //选择XPT2046

   Delay(20);                       //延时

   SPI_WriteByte(0x90);             //设置X轴读取标志

   Delay(20);                       //延时

   x=SPI_WriteByte(0x00);           //连续读取16位的数据

   x<<=8;

   x+=SPI_WriteByte(0x00);

   Delay(20);                       //禁止XPT2046

   TP_DCS();                                                               

   x = x>>3;                        //移位换算成12位的有效数据0-4095

   return (x);

}

u16 TPReadY(void)

{

   u16 y=0;

   TP_CS();                          //选择XPT2046

   Delay(20);                       //延时

   SPI_WriteByte(0xd0);             //设置Y轴读取标志

   Delay(20);                       //延时

   y=SPI_WriteByte(0x00);  //连续读取16位的数据

   y<<=8;

   y+=SPI_WriteByte(0x00);

   Delay(20);    //禁止XPT2046

   TP_DCS();                                                               

   y = y>>3;     //移位换算成12位的有效数据0-4095

   return (y);

}

4.         绘图函数:

void drawbigpoint(u8 x,u16 y)

{

   if(x>220&&y<12)        //如果点击的是左上角CLR字符,就执行清屏指令

   {

        TFT_CLEAR(0,30,240,370); //清屏

   }

   else if(y==0||x==0){        //点击第一个校正点所显示的情形

        TFT_DrawPoint(x,y);//中心点

        TFT_DrawPoint(x+1,y);

        TFT_DrawPoint(x,y+1);

        TFT_DrawPoint(x+1,y+1);

   }       

   else if(x<180&&y<30)     //点击调色板区域,根据点击的坐标选取相应的颜色

   {

       if(x<=30) POINT_COLOR=RED;

        else if(x>60,x<=60) POINT_COLOR=BLUE;

        else if(x>90,x<=90) POINT_COLOR=GREEN;

        else if(x>120,x<=120) POINT_COLOR=GRED;

        else if(x>150,x<=150) POINT_COLOR=BRED;  

        else if(x>180,x<=180) POINT_COLOR=BLACK;

   }

   else if(y>30){     //点击第二个校正点所显示的情形

        TFT_DrawPoint(x,y);

        TFT_DrawPoint(x+1,y);

        TFT_DrawPoint(x,y+1);

        TFT_DrawPoint(x+1,y+1);

   }            

}

5.         采样计算、并画图函数:

void Read_XPT2046(void)

{   float X1,Y1;   

    u8 t,t1,count=0;  

    u16 databuffer[2][30];  //触摸坐标过采样缓冲区

    u16 temp=0;  

    do{                    //循环读数30次       

         X=TPReadX();

         Y=TPReadY();

         if(X>100&&X<4000&&Y>100&&Y<4000)

         {     

             databuffer[0][count]=X;

             databuffer[1][count]=Y;

             count++; 

         }

    }while((PEN==0)&&count<30);     

    if(count==30)   //每次度数一定要读到30次数据,否则丢弃

    { 

        do          //将数据X升序排列

         {    t1=0;   

             for(t=0;t<count-1;t++)

             { if(databuffer[0][t]>databuffer[0][t+1])//升序排列

                  {   temp=databuffer[0][t+1];

                       databuffer[0][t+1]=databuffer[0][t];

                       databuffer[0][t]=temp;

                       t1=1;

                  } 

             }

         }while(t1);

         do          //将数据Y升序排列

         {    t1=0;

             for(t=0;t<count-1;t++)

             {

                  if(databuffer[1][t]>databuffer[1][t+1])//升序排列

                  {

                       temp=databuffer[1][t+1];

                       databuffer[1][t+1]=databuffer[1][t];

                       databuffer[1][t]=temp;

                       t1=1;   

                  } 

             }

         }while(t1);

    }   

    X1=0; Y1=0;

    for(count=10;count<20; count++){

         X1=X1+databuffer[0][count];

         Y1=Y1+databuffer[1][count];

    }   

    X1=X1/10;  Y1=Y1/10;

    if(X1<=4096&&Y1<=4096)      //触摸坐标值应小于4096

    {   

         X=X1;

         Y=Y1;

         if(dw==1){    //如果进行了校正过程

             if(X1<=Xs)X1=0;

             else X1=X1-Xs;

             if(Y1>Ys)Y1=Y1-Ys;

             else Y1=0;

             X=X1/X2; //根据一个像素对应的触摸值,算出屏幕上的实际X坐标

             Y=Y1/Y2; //根据一个像素对应的触摸值,算出屏幕上的实际Y坐标

             drawbigpoint(X,Y);     //在该坐标画点

         }

    }

}   

三、     实验小结与体会:

本次实验是关于触摸屏的实验,在实现过程中有很多错误,主要是因为触摸屏的相关知识书上比较少,通过上网查资料才了解了一些相关的内容,当你触摸屏幕时系统要获取触点的坐标才知道你触摸的屏幕位置,然后在该位置通过计算画出所需要的图形。实验中不知道如何画一个矩形框,所以实验有些不够完善,通过今后的学习,相信可以更加完美的实现实验要求的结果。

四、     教师评语:

更多相关推荐:
软件开发环境与工具实验报告

软件开发环境与工具实验题目实验类型专业班级姓名学号实验报告实验一托盘程序设计托盘程序设计验证性计算机科学与技术系网络工程方向100320xx10033120xx年10月17日实验地点软件实验室二一实验目的通过本...

软件开发环境与工具实验报告-计算机0801

《软件开发环境与工具》实验报告专业:计算机科学与技术班级:08-01姓名:杨**学号:***20XX年4月19日实验一CASE工具PowerDesigner的使用一、实验目的:安装PowerDesigner,并…

软件开发环境与工具实验报告

课程名称实验项目实验地点专业班级学生姓名指导教师本科实验报告软件开发环境与工具软件开发环境与工具实验报告逸夫楼402学号闫伟张辉20xx年11月13日

软件开发环境与工具实验报告 -2

课程名称实验项目本科实验报告软件开发环境与工具软件开发工具及C程序20xx年11月20日

软件开发环境与工具实验报告

学号北京工商大学计算机学院实验报告专业软件工程班级学号姓名20xx20xx学年第2学期20xx年3月至20xx年7月班级学号同组同学学号无姓名注实验内容及步骤项目的内容如果较多可以加附页

软件开发环境与工具实验报告

课程名称软件开发环境与工具实验项目六个实验实验地点逸夫楼402专业班级学号学生姓名指导教师赵荣香20xx年11月19日1实验一CASE工具PowerDesiner的使用一实验目的和要求实验目的安装PowerDe...

软件开发环境与工具实验报告

课程名称实验项目实验地点专业班级学生姓名指导教师本科实验报告软件开发环境与工具学号吕进来20xx年1月3日

《软件开发环境与工具》实验指导书(软件10)

软件开发环境与工具实验指导书太原理工大学计算机科学与技术学院20xx515说明本书适用于计算机科学与技术专业计算机工程专业及软件工程专业软件开发环境与工具的实验指导共8个学时覆盖软件开发的过程涉及当前较流行的软...

软件开发环境与工具实验报告(20xx) - 副本

课程名称实验项目实验地点专业班级学生姓名指导教师本科实验报告名称学号20xx年月日

《软件开发环境与工具》

软件开发环境与工具实验指导书太原理工大学计算机科学与技术学院20xx1027说明本书适用于计算机科学与技术专业计算机工程专业及软件工程专业软件开发环境与工具的实验指导共8个学时覆盖软件开发的过程涉及当前较流行的...

《软件开发环境与工具》实验指导书(20xx)

软件开发环境与工具实验指导书太原理工大学计算机科学与技术学院20xx1104说明本书适用于计算机科学与技术专业计算机工程专业及软件工程专业软件开发环境与工具的实验指导共8个学时覆盖软件开发的过程涉及当前较流行的...

《软件开发环境与工具》实验指导书(现代学院13)

软件开发环境与工具实验指导书太原理工大学计算机科学与技术学院20xx515说明本书适用于计算机科学与技术专业计算机工程专业及软件工程专业软件开发环境与工具的实验指导共8个学时覆盖软件开发的过程涉及当前较流行的软...

软件开发环境与工具实验报告(18篇)