1. 要求实现4个LED灯显示二进制的0-16,每次变幻时间为1s钟,LED灯接入的引脚是 PA5,PA6,PA7,PA8可能用到的函数和头文件如下 delay.h、led.h、Smg.h、Key.h、void Delayms(uint i)、void Delayus(uint a)、Void Led_Init(void)、void key_Init(void) 、void Smg_init()。

2. 要求实现通过按键控制LED灯闪烁、控制数码数码显示202107;实现效果如下:程序开始led灯和数码管保持熄灭,KEY1按键按下LED灯开始闪烁,KEY2按键按下显示202107并保持LED灯闪烁(本题运用的 I/O引脚有 PB1、PB2作为按键KEY1、KEY2;PA1作为LED灯;PC0-PC7作为数码管的断码,PA2-PA7作 为数码管的位码)。 需要注意的是本程序默认的是各硬件已经初始化完毕,初始化调用函数为:

void led_init(); //led初始化函数 
void key_Init(); //按键初始化函数 
void smg_Init(); //数码管初始化函数 
另外可能会用到的函数为: 
Delay(unsigned int count); 
GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); 
GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); 
GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); 
GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

3. 程序要求按键能控制LED灯的启停,LED灯流水8个分别是PA0-PA7,默认程序开始流水灯从PA0流 向PA7,当有按键按下时流水停止,当再次按下时流水灯再次开始流动,按键对应的端口为PB2。初始化的函数 void LED_Init() void Key_Init() void Delayms()

4. 请实现一个数码管显示通过按键key1每按键按下数码管显示内容加1按键key2按下一次显示内容加2 初始化函数自定义。

5. 请实现按键的多点击事件功能

	按键key1按下一次点亮LED1再次按下一次熄灭LED1。
	按键key1按下二次点亮LED2再次按下二次熄灭LED2。
	按键key1按下三次同时点亮LED1,LED2再次按下三次熄灭LED1,LED2。
	按键key1接在PA1 ,LED1接在PA2, LED2接在PA3;初始化函数自定义

6. 请使用定时器实现一个闹钟显示设计,显示内容为时分秒00:00:00通过按键key1,key2实现闹钟定时器时间设置,蜂鸣器实现闹钟声响,蜂鸣器接在PA1 按键key1接在PB1,按键key2接在PB2,初始化函数自定义。

7. 编程实现按键按下后,单片机读取温度传感器的数据并通过串口2发送到上位机,按键接PB0,低电平有效,温度传感器温度范围为-40到125度,当温度大于等于0时,发送温度数据前加上“+”字符,温度小于零时,温度数据前加上“-”字符,数据波特率为9600,程序IO、串口、获取温度由gpio_init()、uart2(9600)、get_tem()代替即可。

8. 编程实现一个时分秒的实时时钟,超过23:59:59后重新变成00:00:00.每秒钟通过串口2将时分秒的3个字节发送到上位机,程序中定时器,串口及定时器中断函数tim2_init(1),uart2(9600),tim2_interrupt()代替即可。

第一题

#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
int i=0;
uint16_t arr[]={0xFFFF,0x1D0,0x1B0,0x190,0x170,0x150,0x130,0x110,0x0F0,0x0D0,0x0B0,0x090,0x070,0x050,0x030,0x010};
int main(void)
{
    Led_Init();
    while(1)
    {
        for(i=0;i<16;i++)
        {
            GPIO_Write(GPIOA,arr[i]);
            Delayms(1000);
        }
    }
}

第二题

#include "stm32f10x.h"
#define KEY1 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)//获取按键接的引脚PB1的状态值,本题没有说明是高有效还是低有效,就默认为低有效,也就是当KEY1为0时,按键按下了
#define KEY2 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2)//获取按键接的引脚PB1的状态值,与上同理
int KEY1_Scan()//按键1的扫描函数
{
    static int key1_val=0;//static表示key1_val只会在第一次调用的时候初始化为0,之后不再将它置为0
    if(KEY1==0)//判断KEY1是否等于0,就是判断按键按下时
         Delay(5);//延时5毫秒
    if(KEY1==0)//若按键还为按下状态
         key1_val=1;//让key_val等于1
    return key1_val;//返回key_val的值
}
int KEY2_Scan()//与KEY1的扫描函数同理
{
    static int key2_val=0;
    if(KEY2==0)
        Delay(5);
    if(KEY2==0)
        key2_val=1;
    return key2_val;
}
int key1=0,key2=0,T_Count=0,i=0;
int duan[]={0x5b,0x3f,0x5b,0x06,0x3f,0x07};
int wei[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb};//本题位码接的引脚为PA2~PA7与书上不同,所以要自己算
//引脚PA2对应数码管第一位,将它置为0就表示,数码管第一位亮,以此类推。
int main(void)
{
    led_init();
    key_init();
    smg_init();
    while(1)
    {
        key1=KEY1_Scan();//将函数返回的值赋给key1
        key2=KEY2_Scan();//将函数返回的值赋给key2
        if(key1)//如果key1的值为真,也就是为1的时候,只有在KEY1按下了key1才会为1
        {
            if(T_Count<=200)//T_count在小于等于200时
                GPIO_ResetBits(GPIOA,GPIO_Pin_1);//灯处于亮的状态,GPIO_ResetBits置0
            else//否则就是T_count大于200时
                GPIO_SetBits(GPIOA,GPIO_Pin_1);//灭灯
            //本题涉及到数码管所以延时函数给的很小,(若延时函数给很大,就无法实现数码管的按键扫描),若用数码管的延时函数,灯的亮灭变化太快,肉眼不可见,所以使用T_count作为一个变量,在下面的Delay(5)每执行一次T_count加一次,在执行200次以前开灯,在200次以后灭灯,在T_count加到400后,将T_count置0,实现循环闪烁
        }
        if(key2)//当按键2按下
        {
            GPIO_Write(GPIOC,duan[i]);//断码
            GPIO_Write(GPIOA,wei[i]);//位码
            i++;//这个就是for循环中的i
            if(i==6)i=0;//表示0~5,也就是数码管的第一位到第六位
        }
        Delay(5);//延时5毫秒
        GPIO_Write(GPIOA,0xfc);//清空位码的显示
        T_Count++;//作为LED灯闪烁的变量
        if(T_Count>400) T_Count=0;//当加到400时,置为0,重新开始加
    }
}

第三题

#include "stm32f10x.h"
#define KEY GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)
int KEY_Scan()
{
    static int key_count=1;//1为开始,0为暂停
    if(KEY==0)
        Delayms(5);
    if(KEY==0)
    {
        key_count=!key_count;
        while(!KEY);
    }
    return key_count;
}
int key=0,count=0,temp=0xfe;
int mian(void)
{
    LED_Init();
    Key_Init();
    while(1)
    {
        key=KEY_scan();
        if(key)
        {
            GPIO_Write(GPIOA,temp);
            count++;
            temp=(temp<<1)+0x01;
          if(count==8) 
					{
						temp=0xfe;
						count=0;
					}
           Delayms(10);
        }
    }
}

第四题

仿真图

#include "stm32f10x.h"
#define KEY1 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_6)
#define KEY2 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)
//PA0~PA7接断码,PB0~PB5接位码,PB6、PB7为按键KEY1和KEY2
void Delayms(int time)
{
	int i,j;
	for(i=0;i!=time;i++)
	{
			 j=2000;
			while(j--);
	}
}
int i=0,key_val=0;
uint16_t wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
uint16_t duan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uint16_t display[]={0x3f,0x3f,0x3f,0x3f,0x3f,0x3f};
int KEY_scan(void)
{
	static int count=0;
	if(KEY1==0||KEY2==0)
	{
		if(KEY1==0)
			Delayms(5);
		if(KEY1==0)
		{
			count++;
			while(!KEY1);
		}
		if(KEY2==0)
			Delayms(5);
		if(KEY2==0)
		{
			count+=2;
			while(!KEY2);
		}
	}
	return count;
}
int main(void)
{	
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin=0xB0;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	
	GPIO_InitStructure.GPIO_Pin =0xff;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin=0x3f;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	 while(1)
   {
			key_val=KEY_scan();
			display[0]=duan[key_val%10];
			display[1]=duan[key_val%100/10];
			display[2]=duan[key_val%1000/100];
			display[3]=duan[key_val%10000/1000];
			display[4]=duan[key_val%100000/10000];
			display[5]=duan[key_val%1000000/100000];
			for(i=0;i<6;i++)
			{
				GPIO_Write(GPIOA,display[i]);
				GPIO_Write(GPIOB,wei[i]);
				Delayms(5);
				GPIO_Write(GPIOB,0x3f);
			}
   }
}

第五题

仿真图

#include "stm32f10x.h"
#define KEY1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1)
void Delayms(int time)
{
	int i,j,t;
	for(i=0;i!=time;i++)
	{
		for(j=0;j<20;j++)
		{
			 t=100;
			while(t--);
		}
	}
}

int KEY_scan(void)
{
	static int count=0,temp=0,T_count=0;
	if(KEY1==0)
	{
		count++;
		while(!KEY1);
	}
	if(count)
		T_count++;
	if(T_count>=200)
	{
		temp=count;
		count=0;
		T_count=0;
		return temp;
	}
	return 0;
}
int key_val=0;
int led1_count=1,led2_count=1,led3_count=1;
int main(void)
{	
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin =GPIO_Pin_2|GPIO_Pin_3;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_SetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_3);
	 while(1)
   {
		 Delayms(10);
			key_val=KEY_scan();
			switch(key_val)
			{
				case 1:if(led1_count) GPIO_ResetBits(GPIOA,GPIO_Pin_2);
								else GPIO_SetBits(GPIOA,GPIO_Pin_2);
								led1_count=!led1_count;
								break;
				case 2:if(led2_count) GPIO_ResetBits(GPIOA,GPIO_Pin_3);
								else GPIO_SetBits(GPIOA,GPIO_Pin_3);
								led2_count=!led2_count;
								break;
				case 3:if(led3_count) GPIO_ResetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_3);
								else GPIO_SetBits(GPIOA,GPIO_Pin_2|GPIO_Pin_3);
								led3_count=!led3_count;
								break;
			}
   }
}

第六题

仿真图

main.c

//以下为main.c
#include "gpio_init.h"
#include "timer.h"

#define KEY1 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)
#define KEY2 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2)

void Delay(unsigned int time);
uint16_t wei[]={0xfe0,0xfd0,0xfb0,0xf70,0xef0,0xdf0,0xbf0,0x7f0};
uint16_t duan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uint16_t display1[]={0x3f,0x3f,0x40,0x3f,0x3f,0x40,0x3f,0x3f};//正常的时间显示
uint16_t display2[8];//定时时的时间显示
int key2_val;//用于切换时、分、秒的加加,初始化为秒加加;KEY2按一下为分加加,再按KEY2一下为时加加,再按KEY2为秒加加,如此循环
int shi=0,fen=0,miao=0;//时分秒
int shi_count=0,fen_count=0,miao_count=0;//定时的时分秒
int i=0,j,flag=0;//i为数码管的for循环,j为判断是否到定时时间的for判断,flag为两个数组判断的中间量
int key_time=0;//用于无按键操作后3秒,恢复时间显示
int State_Pin_3=1;//判断Pin3的状态,用于控制KEY2关闭蜂鸣器
int main()
{
	gpio_init();
	TIM3_Init(999,71999);//一秒的定时
	while(1)
	{
		if(KEY2==0)
		{
			if(State_Pin_3)//当蜂鸣器没有响的时候,为定时设置
			{
				key_time=3;
				key2_val++;
				if(key2_val==3) key2_val=0;
			}
			else//当蜂鸣器响时,为关闭蜂鸣器
			{
				State_Pin_3=1;
				GPIO_SetBits(GPIOA,GPIO_Pin_1);
			}
			while(!KEY2);
		}
		if(KEY1==0)
			{
				key_time=3;
				if(key2_val==0) miao_count++;
				else if(key2_val==1) fen_count++;
				else if(key2_val==2) shi_count++;
				if(miao_count==60)
				{
					miao_count=0;
					fen_count++;
					if(fen_count==60)
					{
						shi_count++;
						if(shi_count==24) shi_count=0;
					}
				}
				while(!KEY1);
			}
		if(key_time)//正在定时操作
		{
			GPIO_ResetBits(GPIOA,GPIO_Pin_2);
			display2[0]=duan[miao_count%10];
			display2[1]=duan[miao_count/10];
			display2[2]=0x40;
			display2[3]=duan[fen_count%10];
			display2[4]=duan[fen_count/10];
			display2[5]=0x40;
			display2[6]=duan[shi_count%10];
			display2[7]=duan[shi_count/10];
			for(i=0;i<8;i++)
			{
				GPIO_Write(GPIOC,display2[i]);
				GPIO_Write(GPIOB,wei[i]);
				Delay(10);
				GPIO_Write(GPIOB,0xff0);
			}
		}
		else//正常时间显示
		{
			GPIO_SetBits(GPIOA,GPIO_Pin_2);
			display1[0]=duan[miao%10];
			display1[1]=duan[miao/10];
			display1[3]=duan[fen%10];
			display1[4]=duan[fen/10];
			display1[6]=duan[shi%10];
			display1[7]=duan[shi/10];
			miao_count=miao;
			fen_count=fen;
			shi_count=shi;
			for(i=0;i<8;i++)
			{
				GPIO_Write(GPIOC,display1[i]);
				GPIO_Write(GPIOB,wei[i]);
				Delay(10);
				GPIO_Write(GPIOB,0xff0);
			}
			for(j=0;j<8;j++)//判断是否到达定时时间
			{
				if(display1[j]==display2[j]) flag++;
				else flag=0;
				if(flag==8) //到达定时时间
				{
					State_Pin_3=0;
					GPIO_ResetBits(GPIOA,GPIO_Pin_1);//蜂鸣器响
				}	
			}
		}
	}
}

void Delay(unsigned int time)
{
	int i,j;
	for(i=0;i!=time;i++)
	{
		j=200;
		while(j--);
	}
}

timer.c

//以下为timer.c
#include "stm32f10x_tim.h"
#include "timer.h"

extern int miao,fen,shi,key_time;

void TIM3_Init(u16 arr,u16 psc)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); 
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
	//中断优先级NVIC设置
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器
	TIM_Cmd(TIM3, ENABLE);  //使能TIMx					 
}
//定时器3中断服务程序
void TIM3_IRQHandler(void)   //TIM3中断
{
	miao++;
	if(miao==60)
		{
			miao=0;
			fen++;
			if(fen==60)
			{
				fen=0;
				shi++;
				if(shi==24) shi=0;
			}
		}
	if(key_time>0)
		key_time--;
	TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除TIM3更新中断标志
}

//以下为gpio_init.c
#include "stm32f10x.h"
#include "gpio_init.h"

//按键、数码管、蜂鸣器初始化
void gpio_init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE);
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	//按键初始化
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_2;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	//蜂鸣器初始化
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;	
	GPIO_InitStructure.GPIO_Pin =GPIO_Pin_1;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_SetBits(GPIOA,GPIO_Pin_1);
	//数码管初始化
	GPIO_InitStructure.GPIO_Pin =0xff0;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin=0xff;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
}

第七题

#include "stm32f10x.h"
#define KEY GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)
void delay_ms(unsigned int time)
{
    int i,t;
    for(i=0;i!=time;i++)
    {
        t=2000;
        while(t--);
    }
}
int tem=0;
char arr[20];
int main(void)
{
    gpio_init();
    uart2(9600);
    while(1)
    {
        if(KEY==0)
            delay_ms(5);
        if(KEY==0)
        {
            tem=get_tem();
            if(tem>=0) arr[0]='+';
            else arr[0]='-';
            arr[1]=tem+'0';
            sendbuffer(arr);
        }
    }
}

第九题

#include "stm32f10x.h"
#include "stm32f10x_tim.h"
int T_miao=0,T_fen=0,T_shi=0;
char arr[3];
void tim2_interrupt()
{
    T_miao++;
    TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
int main(void)
{
    tim2_init(1);
    uart2(9600);
    while(1)
    {
        if(T_mian==60)
        {
            T_miao=0;
            T_fen++;
            if(T_fen==60)
            {
                T_fen=0;
                T_shi++;
                if(T_shi==24)
                    T_shi=0;
            }
        }
        arr[0]=T_miao+'0';
        arr[1]=T_fen+'0';
        arr[2]=T_shi+'0';
        sendbuffer(arr);
    }
}

作者:刮大风了

物联沃分享整理
物联沃-IOTWORD物联网 » 四、STM32练习题

发表回复