【蓝桥杯】单片机设计与开发指南:模板V1.1详解

#include<STC15.H>        // STC15系列单片机头文件
#include<intrins.H>      // 包含内部函数,如_crol_等

#define uchar unsigned char
#define uint unsigned int
    
// LED控制相关定义
unsigned char LED_Bit=0XFF;      // LED状态位,初始全灭(1表示灭,0表示亮)
unsigned char Actuator_Bit=0X00; // 执行器(蜂鸣器/继电器)状态位

// LED控制宏定义
#define LEDx_ON(n)  { LED_Bit&=_crol_(0XFE,n-1); P0=LED_Bit; P2|=0X80; P2&=0X9F; P2&=0X1F;}  // 打开第n个LED
#define LEDx_OFF(n) { LED_Bit|=_crol_(0X01,n-1); P0=LED_Bit; P2|=0X80; P2&=0X9F; P2&=0X1F;} // 关闭第n个LED

// 蜂鸣器和继电器控制宏定义
#define Buzzer_ON   Actuator_Bit|=0x40; P0=Actuator_Bit; P2|=0XA0; P2&=0XBF; P2&=0X1F;      // 打开蜂鸣器
#define Buzzer_OFF  Actuator_Bit&=0XBF; P0=Actuator_Bit; P2|=0XA0; P2&=0XBF; P2&=0X1F;     // 关闭蜂鸣器
#define Relay_ON    Actuator_Bit|=0x10; P0=Actuator_Bit; P2|=0XA0; P2&=0XBF; P2&=0X1F;     // 打开继电器
#define Relay_OFF   Actuator_Bit&=0XEF; P0=Actuator_Bit; P2|=0XA0; P2&=0XBF; P2&=0X1F;     // 关闭继电器

// 数码管相关定义
unsigned char tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF}; // 共阳数码管段码表(0-9,-,全灭)
unsigned char KEY_Value = 0 ;    // 存储按键值
unsigned char DigCom=0;          // 数码管位选计数器
unsigned char DigBuf[8] = {10,10,10,10,10,10,10,10}; // 数码管显示缓冲区(初始显示"-")

// LED流水灯相关变量
unsigned char LED = 1 ;          // 当前点亮的LED编号(1-8)
unsigned int LED_tt =0;          // LED计时计数器
bit LED_Ref = 0 ;                // LED刷新标志

// 数码管倒计时相关变量
unsigned int SEG_tt =0;          // 数码管计时计数器
bit SEG_Ref = 0 ;                // 数码管刷新标志
bit SEG_Run = 0 ;                // 数码管倒计时运行标志
unsigned int Num = 999 ;         // 倒计时初始值999

// 其他功能预留变量
unsigned int XXX_tt =0;          // 预留计时器
bit XXX_Ref =0;                  // 预留刷新标志

// 函数声明
void ALL_Init(void);             // 初始化所有外设
void Delay_MS(unsigned int MS);  // 毫秒级延时
void KeyScan(void);              // 独立按键扫描
void ArrKeyScan(void);           // 矩阵按键扫描(未使用)
void Timer0Init(void);           // 定时器0初始化(1毫秒@11.0592MHz)

// 主函数
void main(void)
{
    ALL_Init();                  // 初始化所有外设
    Timer0Init();                // 初始化定时器0
    EA=1;ET0=1;                  // 开启总中断和定时器0中断
    
    while(1)                     // 主循环
    {
        KeyScan();               // 扫描按键
//      ArrKeyScan();            // 矩阵按键扫描(注释掉未使用)
        
        // 按键处理
        if(KEY_Value==7){KEY_Value=0;SEG_Run = 1 ;} // 按键7:启动倒计时
        if(KEY_Value==6){KEY_Value=0;SEG_Run = 0 ;} // 按键6:停止倒计时
        if(KEY_Value==5){KEY_Value=0;LEDx_ON(1);Buzzer_ON;} // 按键5:打开LED1和蜂鸣器
        if(KEY_Value==4){KEY_Value=0;LEDx_OFF(1);Buzzer_OFF;} // 按键4:关闭LED1和蜂鸣器
        
        // LED流水灯控制
        if(LED_Ref == 1)        // 每999ms刷新一次LED
        {
            LED_Ref = 0 ;        // 清除刷新标志
            LEDx_OFF(LED-1);     // 关闭上一个LED
            LEDx_ON(LED);        // 点亮当前LED
            if (++LED == 9) LED = 1 ; // LED编号循环1-8
        }
        
        // 数码管倒计时处理
        if(SEG_Ref==1)           // 每1000ms刷新一次
        {
            SEG_Ref=0;          // 清除刷新标志
            Num=Num-1;           // 倒计时减1
        }   
        
        // 数码管显示处理
        if(SEG_Run==1)           // 倒计时运行状态下更新显示
        {
            // 高5位数码管显示空白(11对应tab中的全灭)
            DigBuf[3]=11;DigBuf[4]=11;DigBuf[5]=11;DigBuf[6]=11;DigBuf[7]=11;
            // 低3位数码管显示倒计时数值(百位、十位、个位)
            DigBuf[0]=Num/100;DigBuf[1]=Num%100/10;DigBuf[2]=Num%10;
        }       
        
//      if(XXX_Ref==1)          // 预留功能处理
//      {
//          XXX_Ref=0;
//          XXX;
//          DigBuf[0]=XXX/100;DigBuf[1]=XXX%100/10;DigBuf[2]=XXX%10;
//      }           
    }
}

// 独立按键扫描函数
void KeyScan(void)
{
    if(P30==0)                   // 检测P3.0按键
    {
        Delay_MS(10);            // 消抖延时
        if(P30==0)KEY_Value = 7 ; // 确认按键按下,赋值7      
        while(!P30);             // 等待按键释放
    }
    else if(P31==0)             // 检测P3.1按键
    {
        Delay_MS(10);
        if(P31==0)KEY_Value = 6 ;      
        while(!P31);
    }   
    else if(P32==0)             // 检测P3.2按键
    {
        Delay_MS(10);
        if(P32==0)KEY_Value = 5 ;      
        while(!P32);
    }   
    else if(P33==0)             // 检测P3.3按键
    {
        Delay_MS(10);
        if(P33==0)KEY_Value = 4 ;      
        while(!P33);
    }   
}

// 定时器0中断服务函数(1ms中断一次)
void Timer0(void) interrupt 1
{
    // 数码管动态显示处理
    P0=0X00;                    // 先关闭所有段选
    P2|=0XC0;                   // 打开段选锁存器
    P2&=0XDF;                   
    P2&=0X1F;                   // 关闭所有锁存器   
    
    P0=tab[DigBuf[DigCom]];     // 根据显示缓冲区设置当前数码管段选    
    P2|=0XE0;                   // 打开段选锁存器
    P2&=0XFF;                   
    P2&=0X1F;                   // 关闭所有锁存器
    
    P0=(0X01<<DigCom);          // 设置当前数码管位选(1-8) 
    P2|=0XC0;                   // 打开位选锁存器
    P2&=0XDF;                   
    P2&=0X1F;                   // 关闭所有锁存器

    if(++DigCom == 8)DigCom = 0 ; // 数码管位选循环0-7
    
    // LED流水灯计时
    LED_tt++;
    if(LED_tt == 999) {LED_tt = 0 ; LED_Ref = 1 ;} // 每999ms设置LED刷新标志

    // 数码管倒计时计时
    if(++SEG_tt==1000){SEG_tt=0;SEG_Ref=1;} // 每1000ms设置倒计时刷新标志
    
    // 预留功能计时
//  XXX_tt++;
//  if(++XXX_tt==NNN){XXX_tt=0;XXX_Ref=1;}    
}

// 定时器0初始化函数(1毫秒@11.0592MHz)
void Timer0Init(void)       
{
    AUXR |= 0x80;        // 定时器时钟1T模式
    TMOD &= 0xF0;        // 设置定时器模式
    TL0 = 0xCD;          // 设置定时初始值
    TH0 = 0xD4;          // 设置定时初始值
    TF0 = 0;             // 清除TF0标志
    TR0 = 1;             // 定时器0开始计时
}

// 毫秒级延时函数
void Delay_MS(unsigned int MS)
{
    unsigned i,j;
    for(i=0;i<MS;i++)
        for(j=853;j>0;j--); // STC15单片机设置为853; STC8H单片机修改为1109;STC32G单片机修改为427;
}

// 外设初始化函数
void ALL_Init(void)
{
    // 初始化蜂鸣器和继电器(关闭)
    P2=0XA0;             // 打开控制蜂鸣器继电器的74HC573锁存器
    P0=0X00;             // 关闭蜂鸣器继电器
    
    // 初始化LED(全部关闭)
    P2=0X80;             // 打开控制LED灯74HC573锁存器
    P0=0XFF;             // 关闭所有的LED
    
    // 初始化数码管(全部关闭)
    P2=0XC0;             // 打开控制数码管位选的锁存器
    P0=0XFF;             // 选中所有的数码管
    
    P2=0XE0;             // 打开控制数码管段选的锁存器
    P0=0XFF;             // 关闭所有的数码管
    
    P2=0XC0;             // 打开控制数码管位选的锁存器
    P0=0X00;             // 不选中所有的数码管
}

// 矩阵按键扫描函数(代码中有定义但未在主循环中使用)
void ArrKeyScan(void)
{
	unsigned char temp;				//定义局部变量用来存储从P3口读出的数值? 
	P44=0; P42=1; P3=0X7F; 		// //0111 1111 扫描第一列
	temp = P3 ;								//将P3口读出的数字赋值给temp 
	temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
	if(temp != 0X0F)
	{
		Delay_MS(5);
		temp = P3 ;								//将P3口读出的数字赋值给temp 
		temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
		if(temp != 0X0F)
		{
			temp = P3 ;
			switch(temp)  //1110  1101 1011 0111 
			{
				case 0X7E: KEY_Value = 7 ; break;
				case 0X7D: KEY_Value = 6 ; break;
				case 0X7B: KEY_Value = 5 ; break;
				case 0X77: KEY_Value = 4 ; break;
				default :  break;
			}
			while(temp != 0X0F)
			{
				temp = P3 ;								//将P3口读出的数字赋值给temp 
				temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
			}
		}
	}
	
	P44=1; P42=0; P3=0XBF; 		// //0111 1111 扫描第一列
	temp = P3 ;								//将P3口读出的数字赋值给temp 
	temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
	if(temp != 0X0F)
	{
		Delay_MS(5);
		temp = P3 ;								//将P3口读出的数字赋值给temp 
		temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
		if(temp != 0X0F)
		{
			temp = P3 ;
			switch(temp)  //1110  1101 1011 0111 
			{
				case 0XBE: KEY_Value = 11 ; break;
				case 0XBD: KEY_Value = 10 ; break;
				case 0XBB: KEY_Value = 9 ; break;
				case 0XB7: KEY_Value = 8 ; break;
				default :  break;
			}
			while(temp != 0X0F)
			{
				temp = P3 ;								//将P3口读出的数字赋值给temp 
				temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
			}
		}
	}

	P44=1; P42=1; P3=0XDF; 		// //1101 1111 扫描第一列
	temp = P3 ;								//将P3口读出的数字赋值给temp 
	temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
	if(temp != 0X0F)
	{
		Delay_MS(5);
		temp = P3 ;								//将P3口读出的数字赋值给temp 
		temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
		if(temp != 0X0F)
		{
			temp = P3 ;
			switch(temp)  //1110  1101 1011 0111 
			{
				case 0XDE: KEY_Value = 15 ; break;
				case 0XDD: KEY_Value = 14 ; break;
				case 0XDB: KEY_Value = 13 ; break;
				case 0XD7: KEY_Value = 12 ; break;
				default :  break;
			}
			while(temp != 0X0F)
			{
				temp = P3 ;								//将P3口读出的数字赋值给temp 
				temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
			}
		}
	}
	
	P44=1; P42=1; P3=0XEF; 		// //0111 1111 扫描第一列
	temp = P3 ;								//将P3口读出的数字赋值给temp 
	temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
	if(temp != 0X0F)
	{
		Delay_MS(5);
		temp = P3 ;								//将P3口读出的数字赋值给temp 
		temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
		if(temp != 0X0F)
		{
			temp = P3 ;
			switch(temp)  //1110  1101 1011 0111 
			{
				case 0XEE: KEY_Value = 19 ; break;
				case 0XED: KEY_Value = 18 ; break;
				case 0XEB: KEY_Value = 17; break;
				case 0XE7: KEY_Value = 16; break;
				default :  break;
			}
			while(temp != 0X0F)
			{
				temp = P3 ;								//将P3口读出的数字赋值给temp 
				temp = temp & 0X0F ; 			// 0111 XXXX & 0000 1111 = 0000 XXXX 
			}
		}
	}
}

作者:三歪爱三玖

物联沃分享整理
物联沃-IOTWORD物联网 » 【蓝桥杯】单片机设计与开发指南:模板V1.1详解

发表回复