基于STM32单片机的点阵显示设计教材.docx
《基于STM32单片机的点阵显示设计教材.docx》由会员分享,可在线阅读,更多相关《基于STM32单片机的点阵显示设计教材.docx(18页珍藏版)》请在冰豆网上搜索。
基于STM32单片机的点阵显示设计教材
基于STM32单片机的点阵显示设计
一、系统的硬件设计
1.1系统的硬件设计方案
STM32F103x6是基于ARM核心的增强型32位带闪存、USB、ADC和CAN的微控制器。
在电机驱动和应用控制、医疗和手持设备、智能仪表、警报系统和视频对讲中有广泛的应用。
通过使用STM32F103x6进行LED点阵显示的设计,学习STM32单片机的使用方法。
1.2STM32单片机简介
根据本课题需要采用用了STM32F103x6型号单片机STM32F103XX增强型系列拥有ARM的Cortex-M3核心,它为实现MCU的需要提供了低成本、缩减的管脚数目、降低的系统内耗,同时提供了卓越的计算性能和先进的中断系统响应。
它的原理图如图1-2所示。
图1-2STM32单片机原理图
1.2.1STM32F103x6单片机的功能
■核心
--ARM32位的Cortex-M3CPU
--单周期硬件乘法和除法,加快计算
■存储器
--从32K字节到128K字节闪存程序存储器
--多重自举功能
■时钟、复位和供电管理
--2.0至3.6伏供电和I/O管脚
--上电/断电复位、可编程电压检测器、掉电检测器
--内嵌4至16MHZ高速晶体振荡器
--内嵌PLL供应CPU时钟
--内嵌使用32KHZ晶体的RTC振荡器
■低功耗
--3种省电模式:
睡眠、停机和待机模式
--VBAT为RTC和后备寄存器供电
■2个12位模数转换器,1us转换时间
--双采样和保持功能
--温度传感器
■调试模式
--串行调试和JTAG接口
■DMA
--支持的外设:
定时器、ADC、SPI、I2C和USART
■多达80个快速I/O口
--26/36/51/80个多功能双向5V兼容的I/O接口
■多达7个定时器
--多达3个同步的16位定时器,每个定时器有多达4个用于输入捕获/输出比较/PWM或脉冲计数的通道
--两个看门狗定时器
--系统时间定位器:
24位的带自动加载功能的
■多达9个通信接口
--多达2个I2C接口
--多达3个USART接口
--多达2个SPI同步串行接口
--CAN接口
--USB2.0接口
1.2.2STM32单片机的主要特色
STM32系列32位闪存微控制器使用来自于ARM公司具有突破性的Cortex-M3内核,该内核是专门设计于满足集高性能、低功耗、实时应用、具有竞争性价格于一体的嵌入式领域的要求。
Cortex-M3在系统结构上的增强,让STM32受益无穷;Thumb-2®指令集带来了更高的指令效率和更强的性能;通过紧耦合的嵌套矢量中断控制器,对中断事件的响应比以往更迅速;所有这些又都融入了业界领先的功耗水准。
STM32系列给MCU用户带来了前所未有的自由空间,提供了全新的32位产品选项,结合了高性能、实时、低功耗、低电压等特性,同时保持了高集成度和易于开发的优势。
它拥有出众和创新的外设,易于开发,可使产品快速进入市场。
1.3STM32单片机开发板简介
本课题采用了普中科技的STM32开发板,配备有STM32F103x6芯片。
开发板的引脚图如图1-3所示。
图1-3普中科技的STM32开发板实物图
1.3.1STM32开发板的外围硬件资源
--8*8双色点阵模块
--五线四相步进电机
--四线双极性步进电机
--动态数码管/静态数码管
--74HC595
--74HC165
--USB自动下载
--MCU
--矩阵键盘、独立按键
--AD/DA/光敏/温敏
--ISP、PS2
等等。
其电路图如图1-3-1。
图1-3-1普中科技的STM32开发板内部电路图
1.3.2STM32开发板的软件资源
STM32开发板提供了丰富的标准例程,其例程列表如下:
编号
实验名称
编号
实验名称
编号
实验名称
1
LED灯
10
74HC595
19
定时器TIM2
2
RCC系统时钟
11
74HC165
20
串口通信
3
独立按键
12
EXIT中断
21
DS18B20温度检测
4
晶体数码管显示
13
FLASH保存数据
22
RTC时钟
5
动态数码管
14
STM32-24C02
23
ADC1-DMA
6
SysTick定时器
15
STM32-ADDA-PCF8591
24
彩屏例程
7
步进电机
16
STM-1602
25
CAN-BUS
8
矩阵键盘
17
硬件I2C读取24C02
26
VirtualCOMPort(USB转串口)
9
LED点阵
18
硬件SPI-595
1.4硬件电路
本科创课题涉及的硬件电路如图1-4所示。
图1-4STM32LED点阵实验在开发板上的接线图
二、系统的软件设计
对于一个完整的嵌入式应用系统的开发,硬件的设计与调试工作仅占整个工作量的一半,应用系统的程序设计也是嵌入式系统设计一个非常重要的方面。
本次软件编写在Keil软件平台进行的。
如图2-1所示。
图2-1Keil软件平台截图
2.1对STM32端口进行配置
对端口的配置程序如下:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);//关闭调试端口重新映射使用仿真器调试时,不能用此语
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;//所有GPIO为同一类型端口
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//输出的最大频率为50HZ
GPIO_Init(GPIOB,&GPIO_InitStructure);//初始化GPIOB端口
GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化GPIOB端口
2.2控制LED点阵显示的主程序设计
控制LED点阵显示的程序如下:
while
(1)
{
m++;
if(m>4)m=1;
switch(m)
{
case1:
for(j=0;j<3;j++)// //从左到右3次
{
for(i=0;i<8;i++)
{
//P2=taba[i];
GPIOB->BSRR=taba[i]&0x00ff;//将数据送到P2口并屏蔽高位,不干扰高8位IO的使用
GPIOB->BRR=(~taba[i])&0x00ff;
//P1=0xff;
GPIOA->BSRR=0xff&0x00ff;//将数据送到P1口并屏蔽高位,不干扰高8位IO的使用
GPIOA->BRR=(~0xff)&0x00ff;
Delay(0X0DFFFF);
}
}
break;
case2:
Delay(800);
for(j=0;j<3;j++)// //从右到左3次
{
for(i=0;i<8;i++)
{
//P2=taba[7-i];
GPIOB->BSRR=taba[7-i]&0x00ff;//将数据送到P2口并屏蔽高位,不干扰高8位IO的使用
GPIOB->BRR=(~taba[7-i])&0x00ff;
//P1=0xff;
GPIOA->BSRR=0xff&0x00ff;//将数据送到P1口并屏蔽高位,不干扰高8位IO的使用
GPIOA->BRR=(~0xff)&0x00ff;
Delay(0X0DFFFF);
}
}
break;
case3:
Delay(800);
for(j=0;j<3;j++)// //从上至下3次
{
for(i=0;i<8;i++)
{
//P2=0x00;
GPIOB->BSRR=0x00&0x00ff;//将数据送到P2口并屏蔽高位,不干扰高8位IO的使用
GPIOB->BRR=(~0x00)&0x00ff;
//P1=tabb[7-i];
GPIOA->BSRR=tabb[7-i]&0x00ff;//将数据送到P1口并屏蔽高位,不干扰高8位IO的使用
GPIOA->BRR=(~tabb[7-i])&0x00ff;
Delay(0X0DFFFF);
}
}
break;
case4:
Delay(800);
for(j=0;j<3;j++)// //从下至上3次
{
for(i=0;i<8;i++)
{
//P2=0x00;
GPIOB->BSRR=0x00&0x00ff;//将数据送到P2口并屏蔽高位,不干扰高8位IO的使用
GPIOB->BRR=(~0x00)&0x00ff;
//P1=tabb[i];
GPIOA->BSRR=tabb[i]&0x00ff;//将数据送到P1口并屏蔽高位,不干扰高8位IO的使用
GPIOA->BRR=(~tabb[i])&0x00ff;
Delay(0X0DFFFF);
}
}
break;
}
}
}
2.3RCC函数的配置
配置程序代码如下:
voidRCC_Configuration(void)
{
//复位RCC外部设备寄存器到默认值
RCC_DeInit();
//打开外部高速晶振
RCC_HSEConfig(RCC_HSE_ON);
//等待外部高速时钟准备好
HSEStartUpStatus=RCC_WaitForHSEStartUp();
if(HSEStartUpStatus==SUCCESS)//外部高速时钟已经准别好
{
//开启FLASH的预取功能
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
//FLASH延迟2个周期
FLASH_SetLatency(FLASH_Latency_2);
//配置AHB(HCLK)时钟=SYSCLK
RCC_HCLKConfig(RCC_SYSCLK_Div1);
//配置APB2(PCLK2)钟=AHB时钟
RCC_PCLK2Config(RCC_HCLK_Div1);
//配置APB1(PCLK1)钟=AHB1/2时钟
RCC_PCLK1Config(RCC_HCLK_Div2);
//配置PLL时钟==外部高速晶体时钟*9PLLCLK=8MHz*9=72MHz
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);
//使能PLL时钟
RCC_PLLCmd(ENABLE);
//等待PLL时钟就绪
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)
{
}
//配置系统时钟=PLL时钟
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
//检查PLL时钟是否作为系统时钟
while(RCC_GetSYSCLKSource()!
=0x08)
{
}
}
}
2.4NIVC函数配置
配置的程序如下:
voidNVIC_Configuration(void)
{
#ifdefVECT_TAB_RAM
NVIC_SetVectorTable(NVIC_VectTab_RAM,0x0);
#else
NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);
#endif
设置向量表的位置和偏移量,如果向量表位于RAM,则偏移量为0x0。
如果向量位于FLASH则偏移量为0x0。
完整的程序代码见附录。
三、系统实验
首先进行硬件电路搭建,根据图1-4,进行硬件电路连接。
连接完毕后,检查导线是否连接错误以及导线是否连接牢固。
其次进行软件调试,在Keil软件平台进行软件调试,直至无错误报警。
最后将程序下载到开发板。
关键点:
连接时核心板的BOOT1的短路帽要断开。
实验现象:
LED点阵从左到右,从右到左,从上至下,从下至上滚动。
附录
程序代码
#include"stm32f10x_lib.h"
GPIO_InitTypeDefGPIO_InitStructure;
ErrorStatusHSEStartUpStatus;
unsignedinttaba[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsignedinttabb[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
voidRCC_Configuration(void);
voidNVIC_Configuration(void);
voidDelay(vu32nCount);
//主函数
//********************************************************************
intmain(void)
{unsignedchari,j;
staticunsignedcharm;
#ifdefDEBUG
debug();
#endif
RCC_Configuration();//系统时钟配置函数
NVIC_Configuration();//NVIC配置函数
//使能APB2总线外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);//关闭调试端口重新映射使用仿真器调试时,不能用此语
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;//所有GPIO为同一类型端口
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//输出的最大频率为50HZ
GPIO_Init(GPIOB,&GPIO_InitStructure);//初始化GPIOB端口
GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化GPIOB端口
while
(1)
{
m++;
if(m>4)m=1;
switch(m)
{
case1:
for(j=0;j<3;j++)// //从左到右3次
{
for(i=0;i<8;i++)
{
//P2=taba[i];
GPIOB->BSRR=taba[i]&0x00ff;//将数据送到P2口并屏蔽高位,不干扰高8位IO的使用
GPIOB->BRR=(~taba[i])&0x00ff;
//P1=0xff;
GPIOA->BSRR=0xff&0x00ff;//将数据送到P1口并屏蔽高位,不干扰高8位IO的使用
GPIOA->BRR=(~0xff)&0x00ff;
Delay(0X0DFFFF);
}
}
break;
case2:
Delay(800);
for(j=0;j<3;j++)// //从右到左3次
{
for(i=0;i<8;i++)
{
//P2=taba[7-i];
GPIOB->BSRR=taba[7-i]&0x00ff;//将数据送到P2口并屏蔽高位,不干扰高8位IO的使用
GPIOB->BRR=(~taba[7-i])&0x00ff;
//P1=0xff;
GPIOA->BSRR=0xff&0x00ff;//将数据送到P1口并屏蔽高位,不干扰高8位IO的使用
GPIOA->BRR=(~0xff)&0x00ff;
Delay(0X0DFFFF);
}
}
break;
case3:
Delay(800);
for(j=0;j<3;j++)// //从上至下3次
{
for(i=0;i<8;i++)
{
//P2=0x00;
GPIOB->BSRR=0x00&0x00ff;//将数据送到P2口并屏蔽高位,不干扰高8位IO的使用
GPIOB->BRR=(~0x00)&0x00ff;
//P1=tabb[7-i];
GPIOA->BSRR=tabb[7-i]&0x00ff;//将数据送到P1口并屏蔽高位,不干扰高8位IO的使用
GPIOA->BRR=(~tabb[7-i])&0x00ff;
Delay(0X0DFFFF);
}
}
break;
case4:
Delay(800);
for(j=0;j<3;j++)// //从下至上3次
{
for(i=0;i<8;i++)
{
//P2=0x00;
GPIOB->BSRR=0x00&0x00ff;//将数据送到P2口并屏蔽高位,不干扰高8位IO的使用
GPIOB->BRR=(~0x00)&0x00ff;
//P1=tabb[i];
GPIOA->BSRR=tabb[i]&0x00ff;//将数据送到P1口并屏蔽高位,不干扰高8位IO的使用
GPIOA->BRR=(~tabb[i])&0x00ff;
Delay(0X0DFFFF);
}
}
break;
}
}
}
//配置RCC
//********************************************************************voidRCC_Configuration(void)
{
//复位RCC外部设备寄存器到默认值
RCC_DeInit();
//打开外部高速晶振
RCC_HSEConfig(RCC_HSE_ON);
//等待外部高速时钟准备好
HSEStartUpStatus=RCC_WaitForHSEStartUp();
if(HSEStartUpStatus==SUCCESS)//外部高速时钟已经准别好
{
//开启FLASH的预取功能
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
//FLASH延迟2个周期
FLASH_SetLatency(FLASH_Latency_2);
//配置AHB(HCLK)时钟=SYSCLK
RCC_HCLKConfig(RCC_SYSCLK_Div1);
//配置APB2(PCLK2)钟=AHB时钟
RCC_PCLK2Config(RCC_HCLK_Div1);
//配置APB1(PCLK1)钟=AHB1/2时钟
RCC_PCLK1Config(RCC_HCLK_Div2);
//配置PLL时钟==外部高速晶体时钟*9PLLCLK=8MHz*9=72MHz
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);
//使能PLL时钟
RCC_PLLCmd(ENABLE);
//等待PLL时钟就绪
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)
{
}
//配置系统时钟=PLL时钟
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
//检查PLL时钟是否作为系统时钟
while(RCC_GetSYSCLKSource()!
=0x08)
{
}
}
}
//NVIC配置函数
//********************************************************************voidNVIC_Configuration(void)
{
#ifdefVECT_TAB_RAM
/*SettheVectorTablebaselocationat0x20000000*/
NVIC_SetVectorTable(NVIC_VectTab_RAM,0x0);
#else/*VECT_TAB_FLASH*/
/*SettheVectorTablebaselocationat0x08000000*/
NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);
#endif
}
//延时函数
//********************************************************************
voidDelay(vu32nCount)
{
for(;nCount!
=0;nCount--);
}
#ifdefDEBUG
//*********************************************************************FunctionName:
assert_failed
*Description:
Reportsthenameofthesourcefileandthesourcelinenumber
*wherethe