HNU小学期BSP软件编程基础十道测试题

http://t.csdnimg.cn/Yv0R1 文章参考了这位大佬的代码,在他的基础上进行了纠错、完善等处理。

配置

编程前的准备工作按大佬的流程即可,稍有不同的是学习通课程网站的资料里没有头文件的整个压缩包了,但我们可以下载某个BSP版的工程文件,并在里面找到inc文件夹,里面包含所有头文件。

后面把这个文件夹复制到你想要的地方,然后配置的时候引用这个路径就好。

库文件也在刚刚的BSP版的工程文件里面的source里,选择全部文件类型才能看到库文件STCBSP_V3.6.LIB。

不同之处就以上两点,其余的按大佬文中的配置流程即可。

测试题(更新完成)

1、Display: 在数码管指定位置显示指定内容。编写程序,在数码管显示"  12HL- 21" 。
#include "STC15F2K60S2.H"
#include "displayer.H" 
#include "sys.H"


code unsigned long SysClock=11059200;         //必须。 (定义系统工作时钟频率,用户可以修改,且必须与实际工作频率(下载时选择的)一致

#ifdef _displayer_H_                          //显示模块选用时必须。(数码管显示译码表,用戶可修改、增加等) 
code char decode_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x08,0x40,0x01,0x77,0x7c,0x39,0x5e,0x79,0x78,0x76,0x38,0x54,0x5c,0x73,0x67,0x3e,0x6e};  
	              /* 序号:   0    1    2    3    4    5    6    7    8    9    10     11	 12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27 */
                  /* 显示:   0    1    2    3    4    5    6    7    8    9    (无)   下-    中-   上-   A    b    C    d    E    F    H    L    n    o    P    q    U    y */  
#endif



void main()
{  				
	
	displayerInit();                              
	LedPrint(0);
    SetDisplayerArea(0,6);                           
	Seg7Print(1,2,20,21,12,2,1);	 
	MySTC_Init();
	while(1)
		MySTC_OS();
}

按老师要求加上了其他一些字母的编码,修改在decode_table[]中。


2、按键:按下K1,数码管灯显示"H"。松开后灭掉。
#include "STC15F2K60S2.H"
#include "sys.H"
#include "displayer.H"            
#include "key.H" 

code unsigned long SysClock=11059200;

#ifdef _displayer_H_                          
code char decode_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x08,0x40,0x01,0x76,0x38};
                 /* 序号:   0    1    2    3    4    5    6    7    8    9    10     11	 12   13   14   15  */
                 /* 显示:   0    1    2    3    4    5    6    7    8    9    (无)   下-  中-  上-   H    L  */  
 
#endif

char a=10;

void myKey_callback()
{   char k;
	k=GetKeyAct(enumKey1);
	if( k == enumKeyPress ) a=14;
	  else if( k == enumKeyRelease ) a=10;
	Seg7Print(10,10,10,10,10,10,10,a);
}

//void my10mS_callback(){
//Seg7Print(10,10,10,10,10,10,10,a);}

void main(){
	 DisplayerInit();   
	 KeyInit(); 
	 LedPrint(0);
	 SetDisplayerArea(0,7);
	 //SetEventCallBack(enumEventSys10mS, my10mS_callback);
	 SetEventCallBack(enumEventKey, myKey_callback);
	 MySTC_Init();
	 while(1){
		 MySTC_OS();
	 }
}

在系统事件10ms即SetEventCallBack(enumEventSys10mS, my10mS_callback)那里进行了修改,去掉了那句语句,对应的处理函数也可以去掉。因为系统事件10ms会耗费系统资源,不如只用按键事件,并对按键事件处理函数稍作修改即可。

同时注意,当前版本按键初始化KeyInit();中间没有下横线_

3、蜂呜器:开机后发出指定频率。开机后发出1.2KHz 1.8S的声音。
#include "STC15F2K60S2.H"
#include "sys.H"
#include "beep.H"

code unsigned long SysClock=11059200;

int main(){
	
	BeepInit();
	SetBeep(1200,180);
	MySTC_Init();
	while(1)
		MySTC_OS();

}

暂无修改。

SetBeep(1200,180);语句第一个参数指定发声频率,1200表示1.2KHz;第二个参数指定发声时长,发声时长=第二个参数×10,单位为ms,因此发声1.8s时第二个参数为180。更多细节可以看学习板说明文档。

4、音乐:开机后A调,每分钟100拍,播放1、2、3、4、5 (给简谱)。
#include "STC15F2K60S2.H"
#include "sys.H"
#include "displayer.H" 
#include "Beep.H"
#include "music.H"

code unsigned long SysClock=11059200;

#ifdef _displayer_H_ 
code char decode_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x08,0x40,0x01,0x76,0x38};
                 /* 序号:   0    1    2    3    4    5    6    7    8    9    10     11	 12   13   14   15  */
                 /* 显示:   0    1    2    3    4    5    6    7    8    9    (无)   下-  中-  上-   H    L  */  
 
#endif

code unsigned char arr[]={
	0x31,0x10,
	0x32,0x10,
	0x33,0x10,
	0x34,0x10,
	0x35,0x10};

int main(){
	  DisplayerInit();
	  LedPrint(0);
	  SetDisplayerArea(0,7);
	  BeepInit();
	  MusicPlayerInit();
	  SetPlayerMode(enumModePlay);
	  SetMusic(100,0xFA,arr,10,enumMscDrvSeg7andLed);
	  MySTC_Init();
	  while(1){
			MySTC_OS();
		}
	
}

增加了用7段数码管Seg7显示信息和用Led指示灯打拍的功能。

记得添加dispalyer模块,并且指定数码管范围即语句SetDisplayerArea(0,7);

数码管左侧显示每分钟拍数;右侧横线前的数字表示音调,如1代表A调等;横线后数字代表当前音是do、re、mi、fa、so、la、si中的哪一个,如1代表do等。

修改SetMusic(100,0xFA,arr,10,enumMscDrvSeg7andLed);的最后一个参数即可设置是否显示,具体可以看学习板说明文档。


5、秒表:数码管显示分、秒、毫秒。
#include "STC15F2K60S2.H"
#include "sys.H"
#include "displayer.H"  

code unsigned long SysClock=11059200;

#ifdef _displayer_H_
code char decode_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x08,0x40,0x01,0x76,0x38};   
                /* 序号:   0    1    2    3    4    5    6    7    8    9    10     11	 12   13   14   15  */
                /* 显示:   0    1    2    3    4    5    6    7    8    9    (无)   下-  中-  上-   H    L  */  
#endif

long min=0,sec=0,ms=0,temp=0;
char oput[8]={0};

void fun(){
	temp++;
	ms=temp;
	sec=(temp/1000)%60;
	min=temp/60000;
	oput[0]=ms%10;
	oput[1]=(ms/10)%10;
	oput[2]=(ms/100)%10;
	oput[3]=12;
	oput[4]=sec%10;
	oput[5]=(sec/10)%10;
	oput[6]=12;
	oput[7]=min;
	Seg7Print(oput[7],oput[6],oput[5],oput[4],oput[3],oput[2],oput[1],oput[0]);
}

int main(){
	DisplayerInit(); 	
	SetDisplayerArea(0,7);
	Seg7Print(0,0,0,0,0,0,0,0);
	LedPrint(0);
	SetEventCallBack(enumEventSys1mS, fun);
	MySTC_Init();
	while(1)
		MySTC_OS();
}

大佬的原代码中,sec=(temp/1000)%60000;这一行不太对,一分钟是60s,因此temp除了1000以后应该是对60取余而不是60000。

此外,大佬代码中的if(sec>59) sec=sec-60;也不对,由于上面他的代码是取余60000,所以sec可能会比59大,因此需要用到这个if。但是这又带来了另一个问题,就是如果上面计算得到的sec>=120的话,比如sec=121,if语句也只减了一个60,会导致数码管显示秒的部分在2分钟后变为从60开始,61、62、63...而不是从00开始,这也是个bug。

因此,简化代码即可。对应代码改为sec=(temp/1000)%60;并把后面的if语句删去,即可得到正确的逻辑。

由于数码管位数限制,这个程序只能显示10分钟以内的计时。

6、步进电机: 2号电机正转100步(速度:每秒10步)。
#include "STC15F2K60S2.H"
#include "sys.H"
#include "displayer.H"
#include "stepmotor.h"

code unsigned long SysClock=11059200; 

#ifdef _displayer_H_ 
code char decode_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x08,0x40,0x01,0x76,0x38};   
	             /* 序号:   0    1    2    3    4    5    6    7    8    9    10     11	 12   13   14   15  */
                 /* 显示:   0    1    2    3    4    5    6    7    8    9    (无)   下-  中-  上-   H    L  */
#endif

int main(){
	
	  DisplayerInit();
      StepMotorInit();  
	  SetDisplayerArea(0,7);
	  Seg7Print(10,10,10,10,10,10,10,10);
	  LedPrint(0);
	  SetStepMotor(enumStepMotor2,10,100);
	  MySTC_Init();
	  while(1)
		  MySTC_OS();
	
}

暂无修改。

SetStepMotor(enumStepMotor2,10,100);语句第一个参数指定使用2号步进电机:此时,用L0~L3四个LED模拟一个4相步进电机;第二个参数指定速度,单位步/s;第三个参数指定转动步数,正值表示正转,负值表示反转。更多细节可以看学习板说明文档。

7、震动:震动后,蜂鸣器发出Hz频率声音。
#include "STC15F2K60S2.H"
#include "sys.H"
#include "beep.H"   
#include "Vib.h"

code unsigned long SysClock=11059200;

void mysv_callback()
{
	if(GetVibAct()==enumVibQuake)
		SetBeep(1200,100);
}


void main(){
	
	BeepInit();
	VibInit();
	SetEventCallBack(enumEventVib, mysv_callback);
	MySTC_Init();
	while(1)
		MySTC_OS();
	
}

暂无修改。

当Vib检测到有振动发生时,将产生一个“振动事件”enumEventVib,而SetEventCallBack(enumEventVib, mysv_callback);语句设置振动事件用户处理函数,即发生振动事件时,执行函数mysv_callback(),蜂鸣器发出1.2KHz,1s的声音。

8、霍尔:磁场接近时,4个LED向左流水。
#include "STC15F2K60S2.H"
#include "sys.H"
#include "hall.H" 
#include "displayer.H" 

code unsigned long SysClock=11059200L;
#ifdef _displayer_H_                         
code char decode_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x08,0x40,0x01,0x76,0x38};   
	               /* 序号:   0    1    2    3    4    5    6    7    8    9    10     11	 12   13   14   15  */
                   /* 显示:   0    1    2    3    4    5    6    7    8    9    (无)   下-  中-  上-   H    L  */ 
#endif

char ch[8]={0x0f,0x1e,0x3c,0x78,0xf0,0xe1,0xc3,0x87};
int sum=0;
char flag=0;

void my100mS_callback(){
	if(flag){
		if(sum==8) {
		sum=0;
		}
		LedPrint(ch[sum]);
		sum++;
	}
	else{
		LedPrint(0);
		sum=0;
	}
	
}

void myhall(){
	if(GetHallAct()==enumHallGetClose){
		flag=1;
	}
	else{
		flag=0;
	}		
}

void main(){
	DisplayerInit();  
	HallInit(); 
	SetDisplayerArea(0,7);
	Seg7Print(10,10,10,10,10,10,10,10);
	LedPrint(0);
	SetEventCallBack(enumEventSys100mS, my100mS_callback);
	SetEventCallBack(enumEventHall, myhall);
	MySTC_Init();
	while(1)
		MySTC_OS();
}

大佬的代码是一个LED灯在L0~L3之间循环流动,这种理解方式所写代码可参考本文开头列出的文章。

而我的理解是四个灯一起向左流水移动。我按照自己的理解写了这个程序。ch数组控制着LED灯的亮灭。

磁铁靠近时,四个LED灯会向左循环流水;磁铁离开时,LED灯会熄灭,并且下次磁铁靠近时,再次从最右端向左流水。

9、AD:左右导航按键调节初始状态在中间2个LED灯位置。
#include "STC15F2K60S2.H"
#include "sys.H" 
#include "displayer.H"
#include "key.H"
#include "adc.h"  

code unsigned long SysClock=11059200;

#ifdef _displayer_H_
code char decode_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x08,0x40,0x01,0x76,0x38};   
	             /* 序号:   0    1    2    3    4    5    6    7    8    9    10     11	 12   13   14   15  */
                 /* 显示:   0    1    2    3    4    5    6    7    8    9    (无)   下-  中-  上-   H    L  */ 
#endif

unsigned char temp[]={0xc0,0x60,0x30,0x18,0x0c,0x06,0x03,0x81};
int i=3;
void mydh_callback()
{
	if(GetAdcNavAct(enumAdcNavKeyLeft)==enumKeyPress)
	{
		if(i>0)
			i--;
		else i=7;
	}
	else if(GetAdcNavAct(enumAdcNavKeyRight)==enumKeyPress)
	{
		if(i<7)
			i++;
		else i=0;
	}
	LedPrint(temp[i]);
}


void main(){
	DisplayerInit();
	KeyInit();
	AdcInit(ADCexpEXT);
	SetDisplayerArea(0,7);
	LedPrint(temp[3]);
	Seg7Print(10,10,10,10,10,10,10,10);
	SetEventCallBack(enumEventNav, mydh_callback);
	MySTC_Init();
	while(1)
		MySTC_OS();
}

在大佬的代码上稍作了修改,首先将SetEventCallBack(enumEventNav, mydh_callback);语句中的事件换成了专门的导航按键事件enumEventNav。

此外,现在移到边界以后还可以继续移动到另一头,具体可以自己执行试试。

10、AD:光照值小于20,蜂鸣器发1.2KHz频率声音。光照值大于100,蜂鸣器发2KHz频率声音。
#include "STC15F2K60S2.H"
#include "sys.H"
#include "displayer.H"
#include "beep.h"
#include "adc.h"

code unsigned long SysClock=11059200;

#ifdef _displayer_H_ 
code char decode_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x08,0x40,0x01,0x76,0x38};   
	             /* 序号:   0    1    2    3    4    5    6    7    8    9    10     11	 12   13   14   15  */
                 /* 显示:   0    1    2    3    4    5    6    7    8    9    (无)   下-  中-  上-   H    L  */ 

void Rop_callback(){
	if(GetADC().Rop<20)
		SetBeep(1200,150);
	else if(GetADC().Rop>100){
		SetBeep(2000,150);
	}
}
void Per100ms_displayer(){
	char gewei = (GetADC().Rop % 10);
    char shiwei = ((GetADC().Rop) / 10) % 10;
    char baiwei = ((GetADC().Rop) / 100) % 10;
	if(GetADC().Rop>100){
		Seg7Print(10,10,10,10,10,baiwei,shiwei,gewei);
	}
	else{
		Seg7Print(10,10,10,10,10,10,shiwei,gewei);
	}
}

int main(){
	DisplayerInit(); 
	BeepInit();
	AdcInit();
	SetDisplayerArea(0,7);
	Seg7Print(10,10,10,10,10,10,10,10);
	LedPrint(0);
	SetEventCallBack(enumEventSys100mS, Per100ms_displayer);
	SetEventCallBack(enumEventXADC, Rop_callback);
    MySTC_Init();
    while(1){
     MySTC_OS();
	}		
}

在原代码的基础上增加了数码管显示当前光照信息的功能。

注意Seg7Print()函数的参数是char型的。

额外用了100ms系统事件enumEventSys100mS以及对应的用户处理函数来在数码管上显示信息,这是因为如果直接在ADC转换处理函数里来显示信息的话,数值变化就太快了,显示不清。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值