蓝桥杯单片机第十届省赛

题目和完整代码贴在下面了,本文采用互动的方法由大家一起来逐步完善。

具体方法是大家看代码觉得有啰嗦,错误的地方或者有看不懂得地方就在评论区留言,我看到后会在第一时间做详细的解释,修改文章,增加注释。以此来使大家能完全掌握这个题目。

main.c

#include"reg52.h"
#include"smg.h"
#include"iic.h"

sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;
sbit L4 = P0^3;
sbit L7 = P0^6;
sbit L8 = P0^7;


void SMG_XS();

unsigned int channel_three = 0;


unsigned int count_t=0;
unsigned int count_f=0;
unsigned int dat_f=0;
unsigned char state_uf,state_da,i,j,stat_led,stat_smg,stat_led,state_S6,state_S7;


//===============延时=========================
void Delay10ms()        //@11.0592MHz
{
    unsigned char i, j, k;
for(k  = 0;k <= 9;k++)//通过for 实际延时100ms
    {
        i = 108;
    j = 145;
    do
    {
        while (--j);
    } while (--i);
    }
    
}
//========================================

//频率测量模块==========================

void Init_Timer()
{
    TH1 = (65535 - 1000)/256;//1ms
    TL1 = (65535 - 1000)%256;
    
    TH0 = 0xff;
    TL0 = 0xff;
    
    TMOD = 0X16;
    
    EA = 1;
    ET1 = 1;
    ET0 = 1;
    
    TR0 = 1;
    TR1 = 1;
}

void Service_T0() interrupt 1
{
    count_f++;
}
void Service_T1() interrupt 3
{
    TH1 = (65535 - 1000)/256;
    TL1 = (65535 - 1000)%256;
    
    SMG_XS();
    count_t++;
    if(count_t%100 == 0)//每100ms对LED状态更新一次
    {
        if(state_S6 == 0)//S6具有禁用LED功能,设置一个由按键S6控制的状态参数在此判断
        {
            InitHC138(4);
            P0 = stat_led;
            InitHC138(0);
        }
    }
    if(count_t==1000)
    {
        dat_f = count_f;
        count_t=0;
        count_f=0;
    }
}

void SMG_XS()
{
    if(state_S7 == 0)//S7具有禁用数码管功能,设置一个由按键S7控制的状态参数在此判断
    {
        if(state_uf == 0)//显示电压的部分
    {
        i++;
            if(i == 8)
        {
            i = 0;
        }
    switch(i)
    {
        case 0 :
            DisPlaySMG_Bit(0,0xc1);//1100 0001
        break;
        case 1:
            DisPlaySMG_Bit(1,0xff);
        break;
        case 2:
            DisPlaySMG_Bit(2,0xff);
        break;
        
        case 3:
            DisPlaySMG_Bit(3,0xff);
        break;
        case 4:
            DisPlaySMG_Bit(4,0xff);
        break;
        
        
        case 5:
            DisPlaySMG_Bit(5,SMGDot_CA[channel_three*5/256]);//括号不要乱加,如果是(5/256)结果是0
        break;
        case 6:
            DisPlaySMG_Bit(6,SMGNoDot_CA[channel_three*50/256%10]);//结果是 0.00 的形式,我们要小数点后一位,要在  前面  先乘以10,得到一个二位数去取余
        break;
        case 7:
            DisPlaySMG_Bit(7,SMGNoDot_CA[channel_three*500/256%10]);//同样,乘以100要放在前面,如果先除256取整,得到的是0,再乘100也没有意义了
        break;
    }
    }
    
    if(state_uf == 1)//显示频率的部分
    {
        j++;
        if(j == 8)
        {
            j = 0;
        }
        switch(j)
        {
            case 0:
            DisPlaySMG_Bit(0,SMGNoDot_CA[15]);
            break;
            
            case 1:
            DisPlaySMG_Bit(1,0xff);
            break;
            
            case 2:
            DisPlaySMG_Bit(2,0xff);
            break;
            
            
            case 3:
                if(dat_f > 9999)
    {
        DisPlaySMG_Bit(3,SMGNoDot_CA[dat_f/10000]);
    }
            break;
    
            case 4:
            if(dat_f > 999)
    {
        DisPlaySMG_Bit(4,SMGNoDot_CA[(dat_f/1000)%10]);
    }
            break;
            
            case 5:
            if(dat_f > 99)
    {
        DisPlaySMG_Bit(5,SMGNoDot_CA[(dat_f/100)%10]);
    }
            break;
            case 6:
            if(dat_f > 9)
    {
        DisPlaySMG_Bit(6,SMGNoDot_CA[(dat_f/10)%10]);
    }
            break;
            case 7:
            DisPlaySMG_Bit(7,SMGNoDot_CA[(dat_f/1)%10]);
            break;
    
      }
    }
    }
    
}

//===============按键============================
void delayk(unsigned char time)
{
    while(time--);
}

void ScanKeys()
{
    if(S4 == 0)//控制测量电压还是频率
    {
        delayk(100);
        if(S4 == 0)
        {
            while(S4 == 0);
            stat_led = (stat_led | 0x03) & (~stat_led | 0xfc);//S4按下,测量状态切换,这里对L1 L2 两个灯取反
            if(state_uf == 1)
            {
                state_uf = 0;//转为测电压
            }
            
            else//这里不能用连用两个if 因为经过上面的if后,state的值被改变了
            {
                state_uf = 1;
            }
            
        }
    }
    if(S5 == 0)//状态0 输出2V 状态1 输出跟随ad
    {
        delayk(100);
        if(S5 == 0)
        {
            while(S5 == 0);
            stat_led = (stat_led | 0x10) & (~stat_led | 0xef);
            if(state_da == 1)
            {
                state_da = 0;
                write_8591(102);
            }
            
            else
            {
                state_da = 1;
                write_8591(channel_three);
    
            }
        }
    }

    if(S6 == 0)
    {
        delayk(100);
        if(S6 == 0)
        {
            while(S6 == 0);
            if(state_S6 == 0)
            {
                state_S6 = 1;//L6状态参数,为1时将不能对LED进行操作(除此处外唯一能对LED操作的在中断服务函数中,在服务函数中会进行判断)
                InitHC138(4);
                P0 = 0xff;
                InitHC138(0);
            }
            
            else
            {
                state_S6 = 0;
            }
        }
    }
    if(S7 == 0)
    {
        delayk(100);
        if(S7 == 0)
        {
            while(S7 == 0);
            if(state_S7 == 0)
            {
                state_S7 = 1;
                All_SMG();
            }
            
            else
            {
                state_S7 = 0;
            }
        }
    }
}
//==========================

//===============================================
void main()
{
    Init_Timer();
    InitHC138(4);
    stat_led = 0xfe;
    P0 = stat_led;//1111 1110
    InitHC138(0);
    while(1)
    {
        ScanKeys();
        
        channel_three = red_8591(3);
        Delay10ms();
        if(channel_three < 77 || (channel_three < 179 && channel_three > 127))
        {
            stat_led = (stat_led | 0x04) & 0xff;//把L3置1
        }
        if((channel_three > 77 && channel_three < 127)|| channel_three > 179)//||逻辑运算符
        {
            stat_led = (stat_led | 0x04) & 0xfb;//把L3置0
        }
        if(dat_f < 1000 || (dat_f >= 5000 && dat_f < 10000))
        {
            stat_led = (stat_led | 0x08) & 0xff;
        }
        if(dat_f >= 10000 || (dat_f >= 1000 && dat_f < 5000))
        {
            stat_led = (stat_led | 0x08) & 0xf7;
        }
    }
        
}

smg.c

#include"reg52.h"


void InitHC138(unsigned char n)
{
    switch(n)
    {
        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;
        case 0:
            P2 = (P2&0X1F) | 0X00;
        break;
    }
}
//================ÑÓʱ================
void DelaySMG(unsigned char t)
{
    while(t--);
}

void DisPlaySMG_Bit(unsigned char pos,unsigned char dat)
{
    P0 = 0xff;
    InitHC138(6);
    P0 = 0X01 << pos;
    InitHC138(7);
    P0 = dat;
}
//==========================
void All_SMG()//ÏûÓ°
{
    InitHC138(6);
    P0 = 0xff;
    InitHC138(7);
    P0 = 0xff;
}

iic.c

//pcf8591µÄ¶Áд



#include "reg52.h"
#include "intrins.h"

#define DELAY_TIME 5

#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

sbit SDA = P2^1;  
sbit SCL = P2^0;  

void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}
//×ÜÏßÆô¶¯Ìõ¼þ
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;    
}

//×ÜÏßÍ£Ö¹Ìõ¼þ
void IIC_Stop(void)
{
    SDA = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//·¢ËÍÓ¦´ð
void IIC_SendAck(bit ackbit)
{
    SCL = 0;
    SDA = ackbit;                      // 0£ºÓ¦´ð£¬1£º·ÇÓ¦´ð
    IIC_Delay(DELAY_TIME);
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SCL = 0; 
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//µÈ´ýÓ¦´ð
bit IIC_WaitAck(void)
{
    bit ackbit;
    
    SCL  = 1;
    IIC_Delay(DELAY_TIME);
    ackbit = SDA;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

//ͨ¹ýI2C×ÜÏß·¢ËÍÊý¾Ý
void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for(i=0; i<8; i++)
    {
        SCL  = 0;
        IIC_Delay(DELAY_TIME);
        if(byt & 0x80) SDA  = 1;
        else SDA  = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        byt <<= 1;
        IIC_Delay(DELAY_TIME);
    }
    SCL  = 0;  
}

//´ÓI2C×ÜÏßÉϽÓÊÕÊý¾Ý
unsigned char IIC_RecByte(void)
{
    unsigned char i, da;
    for(i=0; i<8; i++)
    {   
        SCL = 1;
    IIC_Delay(DELAY_TIME);
    da <<= 1;
    if(SDA) da |= 1;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    }
    return da;    
}

void write_8591(unsigned char dac)
{
    IIC_Start();
    IIC_SendByte(0x90);//дµØÖ·
    IIC_WaitAck();
    
    IIC_SendByte(0x40);//д¿ØÖÆ×Ö½Ú Ä£ÄâÊä³öʹÄÜ£¬daģʽ
    IIC_WaitAck();
    
    IIC_SendByte(dac);//дÊý¾Ý 
    IIC_WaitAck();
    
    IIC_Stop();
}

unsigned int  red_8591(unsigned int channle_n)
{
    IIC_Start();
    IIC_SendByte(0x90);//дµØÖ·
    IIC_WaitAck();
    
    IIC_SendByte(channle_n);//д¿ØÖÆ×Ö½Ú adģʽ
    IIC_WaitAck();
    
    IIC_Start();
    IIC_SendByte(0x91);//¶ÁµØÖ·
    IIC_WaitAck();
    
    channle_n = IIC_RecByte();
    IIC_SendAck(0);
    channle_n = IIC_RecByte();//ÿ´Î¶Áµ½µÄ¶¼ÊÇÉÏÒ»´Îת»¯µÃµ½µÄ½á¹û,ËùÒÔ¶ÁÁ½´Î

    IIC_Stop();
    
    return channle_n;
}
 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值