蓝桥杯基础

文章介绍了蓝桥杯竞赛中涉及的单片机编程技术,包括延时函数的实现、HC573选择器的初始化,以及LED、蜂鸣器、继电器的控制。此外,还涵盖了基本驱动模块如LED控制、SMG显示、按键扫描,以及定时器中断、DS18B20温度传感器、IIC通信(如AT24C02和PCF8591)、DS1302实时时钟和NE555定时器的应用。
摘要由CSDN通过智能技术生成

蓝桥杯

System

  • 延时程序

    	延时函数均可由stc—isp生成
    	void delay_us(uint xus)		//@12.000MHz
        void delay_ms(uint xms)		//@12.000MHz
    
  • sys初始化

    	//	hc573选择
    	void	hc573(uchar channel)
    {
    	switch(channel)
    	{
    		case 4:	P2 = P2&0x1f | 0x80;
    			break;
    		case 5:	P2 = P2&0x1f | 0xa0;
    			break;
    		case 6:	P2 = P2&0x1f | 0xc0;
    			break;
    		case 7:	P2 = P2&0x1f | 0xe0;
    			break;
    	}
    	P2 = P2&0x1f;
    }
    
        void sys_init()	// 关闭LEd和蜂鸣器,继电器
        {
            P0 = 0xff;
            hc573(4);
            P0 = 0x00;
            hc573(5);			
        }
    

Drivers

  • 基本模块(三大金刚)

    • LED

      void led_contral(uchar *q)
      {
          uchar i;
          uchar temp;
          for(i=0;i<8;i++)
          {
              if(q[i])
                  temp &= ~(0x01 << i);
              else
                  temp|=0x01<<i;
          }
          P0 = temp;
          hc573(4);
      }
      // 可选择分别对 蜂鸣器  继电器选控
      void beep_contral(bit enable);
      void relay_contral(bit enable);
      
    • SMG

      //	定义一个SMG数组,方便使用。
      code uchar segment[] = {};
      //	直接对数组操作
      void seg_contral(uchar *smg,uchar *dot)
      {
      	uchar pos;
      	P0 = 0xff;
      	hc573(7);
      	P0 = 0x01 << pos;
      	hc573(6);
      	if(dot[pos])
      		P0 = segment[smg[pos]] & 0x7f;
      	else
      		P0 =	segment[smg[pos]];
      	hc573(7);
      	pos = (pos + 1) % 8;
      }
      
    • KEy

      	//	注意独立按键和矩阵按键
      uchar	key_scan()
      {
      	if((key_up==1)&&(P30==0||P31==0||P32==0||P33==0))	//独立按键有按键按下
      	{
      		delay_ms(20);
      		key_up = 0;
      		if(P30==0)				return 1;
      		else if(P31==0)		return 2;
      		else if(P32==0)		return 3;
      		else if(P33==0)		return 4;
      		else	return 0;
      	}
      	else if(P30==1&&P31==1&&P32==1&&P33==1)//独立按键有按键按下,已经松手
      	{
      		key_up = 1;
      		return 0;
      	}
      	else
      		return 0;
      }
      uchar key_scan_2()
      {
      	uchar key;
      	P44 = P42 = P35 = P34 = 1;
      	P30 = P31 = P32 = P33 = 0;
      	if(key_up == 1 && (P44 == 0 || P42 == 0|| P35 ==0 || P34 == 0))
      	{
      		delay_ms(20);
      		if(P44 == 0 )			key = 1;
      		else if (P42 == 0)	key = 2;
      		else if (P35 == 0)	key = 3;
      		else if	(P34 == 0)	key = 4;
      		else 	return 0;
      		
      		P44 = P42 = P35 = P34 = 0;
      		P30 = P31 = P32 = P33 = 1;
      		if(P30 == 0)	return key+0;
      		else if (P31 == 0)	return key+4;
      		else if (P32 == 0)	return key+8;
      		else if (P33 == 0)	return key+12;
      		else return 0;
      	}
      	else key_up = 1;	return 0;
      }
      
  • 拓展模块 - - 一般只有省赛考

    • 定时器 + 中断

      	// 用stc—isp可分别生成0,1,2的定时器
          /* 定时器0中断初始化函数 */
          void Timer0Init(void)		//1毫秒@12.000MHz
          {
              AUXR &= 0x7F;		//定时器时钟12T模式
              TMOD &= 0xF0;		//设置定时器模式
              TL0 = 0x18;		//设置定时初始值
              TH0 = 0xFC;		//设置定时初始值
              TF0 = 0;		//清除TF0标志
              TR0 = 1;		//定时器0开始计时
              ET0 = 1;    //定时器中断0打开
              EA = 1;     //总中断打开
          }
      
    • Ds18b20

      初始化–发送跳过指令(0xcc)-- 发送温度转换(0x44)–初始化 – 发送跳过指令(0xcc)–发送读取温度寄存器(0xbe)-- 先后读取低->高八位温度数据,整合成16位数据,再返回temp

      	// 开机的85°,可以先在whlie前面读取一次温度,在延时750ms,即可消除
      	uint temp_read(uchar dot)
      {
      	uint temp;
      	uchar tmh,tml;
      	init_ds18b20();
      	Write_DS18B20(0xcc);
      	Write_DS18B20(0x44);
      	
      	init_ds18b20();
      	Write_DS18B20(0xcc);
      	Write_DS18B20(0xbe);
      	tml = Read_DS18B20();
      	tmh = Read_DS18B20();
      	temp = (tmh << 8) | tml;
      	switch(dot)
      	{
      		case 0:	temp *=0.0625;
      			break;
      		case 1:	temp *=0.625;
      			break;
      		case 2:	temp *=6.25;
      			break;
      	}
      	return temp;
      }
      
      
    • IIC (At24c02和Pcf8591)

      两者都是IIC协议,只是两者的地址不同:一个0xa0,宁一个0x90

      at24c02
          void AT24C02_read_page(uchar *dat,uchar addr,uchar num)
      {
      	uchar date;
      	I2CStart();
      	I2CSendByte(0xa0);
      	I2CWaitAck();
      	I2CSendByte(addr);
      	I2CWaitAck();
      	
      	I2CStart();
      	I2CSendByte(0xa1);
      	I2CWaitAck();
      	while(num--)
      	{
      		*dat = I2CReceiveByte();
      		if(num)
      			I2CSendAck(0);
      		else
      			I2CSendAck(1);
      	}
      	I2CStop();
      }
      
      void AT24C02_write_page(uchar *dat,uchar addr,uchar num)
      {
      	I2CStart();
      	I2CSendByte(0xa0);
      	I2CWaitAck();
      	I2CSendByte(addr);
      	I2CWaitAck();
      	while(num--)
      	{
      		I2CSendByte(*dat++);
      		I2CWaitAck();		
      	}
      	I2CStop();
      }
      
      Pf8591
          void PCF8591_write(uchar date)
      {
      	I2CStart();
      	I2CSendByte(0x90);
      	I2CWaitAck();
      	I2CSendByte(0x40);
      	I2CWaitAck();
      	I2CSendByte(date);
      	I2CWaitAck();
      	I2CStop();
      }
      uchar PCF8591_read(uchar channel)
      {
      	uchar date;
      	I2CStart();
      	I2CSendByte(0x90);
      	I2CWaitAck();
      	I2CSendByte(channel);
      	I2CWaitAck();
      	I2CStart();
      	I2CSendByte(0x91);
      	I2CWaitAck();
      	date = I2CReceiveByte();
      	I2CSendAck(1);
      	I2CStop();
      	return date;
      }
          
          
      
  • Ds1302

    	定义三个数组,分别存放写地址,读地址,和存取的时间
    code uchar write_addr[] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
    code uchar read_addr[]	={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
    uchar time[] = {0x00,0x00,0x12,0x06,0x04,0x04,0x23};
    
    void ds1302_init()
    {
    	uchar i;
    	Write_Ds1302_Byte(0x8e,0x00);
    	for(i=0;i<7;i++)
    	{
    		Write_Ds1302_Byte(write_addr[i],time[i]);
    	}
    	Write_Ds1302_Byte(0x8e,0x80);
    }
    void ds1302_read()
    {
    	uchar i;
    	for(i=0;i<7;i++)
    	{
    		time[i]=Read_Ds1302_Byte(read_addr[i]);
    	}
    }
    
  • ne555

    	用定时器来读取
            void TimerInit()
    {
    	TMOD = 0x05;       //方法二
    	TL0 = 0x00;
    	TH0 = 0x00;
    	TL1 = (65536 - 50000) %256;
    	TH1 = (65536 - 50000) /256;
    	EA = 1;
    	ET0 = ET1 =1;
    	TR0 = TR1 =1;
    }
    void timer1() interrupt 3
    {
    	count2++;
    	if(count2 == 20)	// 每一秒进入一次
    	{
    		Fre = TL0 + TH0 *256;
    		TL0 = 0x00;
    		TH0 = 0x00;	// 每读取一次手动重装一次
    		count2 = 0;
    	}
    }   
    
  • 进阶模块 - - 一般都是国赛考

    • 超声波
    • 串口通讯

User

  • main函数

    • 定义各种变量,参数,数组,标志位等

      // main函数一般只存放这些,其他的在定时器中补充,或者在初始化中初始化
      void main()
      {
      	sys_init();
      	while(1)
      	{
      		key_pro();
      		smg_pro();
      		led_pro();
      	}		
      }
      
    • 补充

      多利用如下写法,提高效率。

      void led_pro()
      {
      	if(led_state)	return;
      	led_state = 1;
      	led_contral(led_buf);
      }
      void Timer1(void)		interrupt 3
      {
      	if(++led_state==50)	led_state=0;
      }
      

一些思维导图

蓝桥杯_Plus蓝桥杯_单片机_模块化蓝桥杯_单片机_模板化

void led_pro()
{
if(led_state) return;
led_state = 1;
led_contral(led_buf);
}

  void Timer1(void)		interrupt 3
  {
  	if(++led_state==50)	led_state=0;
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值