学习51的时候看了定时器设计的门铃,在32之中我将其用滴答计时器实现。
将程序下载到开发板上之后,按下上键蜂鸣器会发出ding,dong的声音,然后停下不发声,程序中使用led1来检测我们的程序是否正常的在运作中
main.c
/*************************************************************************
* 实验现象 : 按下ZET6板子的上键会发出叮咚的响声,类似于门铃
* 2020-2-14 12:26
**************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "beep.h"
#include "key.h"
#define ModeNum 2
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
u16 j = 0, n, flag, i;
u8 ding, dong;
SysTick_Init(72);
LED_Init();
BEEP_Init();
KEY_init();
while(1)
{
j = KEY_Scan(0); //使用j变量获取按键按下的键
if(j == KEY_UP) //按下上键表示按下门铃
{
flag = 0;
}
if(flag != ModeNum) //在flag为0/1模式才进行i的++
{
i++;
}
//if(i == 1000) 此处与后面的delay注释又是一组响声
if(i == 2000)
{
i = 0;
if(flag < ModeNum)
{
flag++;
}
}
if(flag == 0) //flag为0的时候发出ding的声音
{
ding++;
if(ding == 1)
{
ding = 0;
beep = ~beep;
}
}
else if(flag == 1) //flag为1的时候发出dong的
{
dong++;
if(dong == 2)
{
dong = 0;
beep = ~beep;
}
}
n++;
if(n%250 == 0)
led1=!led1;
delay_us(250);
//delay_us(500);
}
}
beep.h
#ifndef _beep_H
#define _beep_H
#include "system.h"
/* 蜂鸣器时钟端口、引脚定义 */
#define BEEP_PORT GPIOB
#define BEEP_PIN GPIO_Pin_5
#define BEEP_PORT_RCC RCC_APB2Periph_GPIOB
#define beep PBout(5)
void BEEP_Init(void);
#endif
beep.c
#include "beep.h"
/*******************************************************************************
* 函 数 名 : BEEP_Init
* 函数功能 : 蜂鸣器初始化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void BEEP_Init() //端口初始化
{
GPIO_InitTypeDef GPIO_InitStructure; //声明一个结构体变量,用来初始化GPIO
RCC_APB2PeriphClockCmd(BEEP_PORT_RCC,ENABLE); /* 开启GPIO时钟 */
/* 配置GPIO的模式和IO口 */
GPIO_InitStructure.GPIO_Pin=BEEP_PIN; //选择你要设置的IO口
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //设置推挽输出模式
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //设置传输速率
GPIO_Init(BEEP_PORT,&GPIO_InitStructure); /* 初始化GPIO */
}
key.h
#ifndef _KEY_H
#define _KEY_H
#include "system.h"
#define KEY_UP_Pin GPIO_Pin_0
#define KEY_DOWN_Pin GPIO_Pin_3
#define KEY_LEFT_Pin GPIO_Pin_2
#define KEY_RIGHT_Pin GPIO_Pin_4
#define KEY_PORT GPIOE
#define KEY_UP_PORT GPIOA
//使用位操作定义
#define K_UP PAin(0)
#define K_DOWN PEin(3)
#define K_LEFT PEin(2)
#define K_RIGHT PEin(4)
//定义各个按键值
#define KEY_UP 1
#define KEY_DOWN 2
#define KEY_LEFT 3
#define KEY_RIGHT 4
void KEY_init(void);
u8 KEY_Scan(u8 mode);
#endif
key.c
#include "key.h"
#include "Systick.h"
void KEY_init(void)
{
GPIO_InitTypeDef GPIO_InitSturcture;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitSturcture.GPIO_Mode=GPIO_Mode_IPD;
GPIO_InitSturcture.GPIO_Pin=KEY_UP_Pin;
GPIO_InitSturcture.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(KEY_UP_PORT,&GPIO_InitSturcture);
GPIO_InitSturcture.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitSturcture.GPIO_Pin=KEY_DOWN_Pin|KEY_LEFT_Pin|KEY_RIGHT_Pin;
GPIO_InitSturcture.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(KEY_PORT,&GPIO_InitSturcture);
}
//0-单 1-多
u8 KEY_Scan(u8 mode)
{
static u8 key = 1;
if(key == 1 && (K_UP ==1 || K_LEFT==0||K_RIGHT==0||K_DOWN==0))
{
delay_ms(10);
//单次
key=0;
if(K_UP ==1 )
{
return KEY_UP;
}
else if(K_LEFT==0)
{
return KEY_LEFT;
}
else if(K_RIGHT == 0)
{
return KEY_RIGHT;
}
else if(K_DOWN==0)
{
return KEY_DOWN;
}
}
else if(K_UP==0&&K_DOWN==1&&K_LEFT==1&&K_RIGHT==1) //无按键按下
{
key=1;
}
if(mode == 1)
{
key=1;
}
return 0;
}
Systick.h
#ifndef _SysTick_H
#define _SysTick_H
#include "system.h"
void SysTick_Init(u8 SYSCLK);
void delay_ms(u16 nms);
void delay_us(u32 nus);
#endif
Systick.c
#include "SysTick.h"
static u8 fac_us=0; //us延时倍乘数
static u16 fac_ms=0; //ms延时倍乘数
//初始化延迟函数
//SYSTICK的时钟固定为AHB时钟的1/8
//SYSCLK:系统时钟频率
void SysTick_Init(u8 SYSCLK)
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
fac_us=SYSCLK/8;
fac_ms=(u16)fac_us*1000;
}
//延时nus
//nus为要延时的us数.
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us; //时间加载
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}