【第十四届蓝桥杯单片机模拟题2】(深夜学习——单片机)

一、宏定义

#ifndef PUBLIC_H
#define PUBLIC_H

#include <STC15F2K60S2.H>
#include "intrins.h"
#define u8 unsigned char
#define u16 unsigned int


#endif

二、主函数:

#ifndef MAIN_H
#define MAIN_H

#include "Public.h"
#include "stdio.h"
#include "Device.h"
#include "Uart.h"
#include "string.h"
#include "iic.h"

//模式切换
u8 seg_mode; //0为噪声显示模式
char set_num;
u8 nose_sign;
u8 count_1ms;
//串口
char uart_temp[7];
u8 uart_temp1;
u8 r_sign,r_num;
u8 r_temp;
//数码管
u16 seg_delay;
u8 COT[10],COD[8],PSI;
//按键
u8 key_delay;
//LED
u8 l_data;
//PCF8591
float volt_num,nose;
#endif
// 40
#include "main.h"
void SEG_Proc();
void Key_Proc();
void Init();
void main()
{
	 All_Close();
	 UartInit();
	 Timer1Init();
	 Init();	
	 while(1)
	 {
		SEG_Proc();
		Key_Proc();

	 }
}

void Uart_IT(void) interrupt 4
{
	if(RI)
	{
		RI = 0;
		
		if(uart_temp1 == 'R')
		{
			uart_temp[0] = 'R';
			uart_temp[r_num] = SBUF;
			if(++r_num == 6)
			{
				r_num = 0;
				r_sign = 1;
				uart_temp1 = 0;
			}
		}
		else
		{
			uart_temp1 = SBUF;
			r_num = 1;
		}
			
	}
}

void T1_IT() interrupt 3
{
	if(++seg_delay == 500)seg_delay = 0;
	if(++key_delay == 10)key_delay = 0;

	SEG_Show(COD[PSI],PSI);
	if(++PSI == 8)PSI = 0;

	if(nose_sign)
	{	
		if(++count_1ms == 101)
		{
			count_1ms = 0;
			l_data ^= 0x80;
		}
	}
	else
		l_data &= ~0x80;
	LED_Show(l_data);
}
void SEG_Proc()
{
	u8 i;
	if(seg_delay)return;
	seg_delay = 1;

	//噪声测量
	volt_num = 	PCF8591_ADC()/255.0*5;
    nose = 	volt_num*18;
	//L8
	if(nose>set_num)
	{
		//开始计数
		count_1ms = 0;
		nose_sign = 1;
	}
	else
		nose_sign = 0;
	//参数模式
	if(seg_mode)
	{
		sprintf(COT,"U2    %2u",(u16)set_num);	
	}
	else //显示模式
	{
		sprintf(COT,"U1   %4.1f",nose);
		if(r_sign)
		{
			r_sign = 0;
			if(strcmp(uart_temp,"Return") == 0)	
				printf("Noises:%4.1fdB\r\n",nose);
		}
	}
	SEG_TSL(COT,COD);
}

void Key_Proc()
{
	static u8 key_old;
	u8 key_now,key_down;
	if(key_delay)return;
	key_delay = 1;

	key_now = M_Key();
	key_down = key_now & (key_now ^ key_old);
	key_old = key_now;

	//全模式
	if(key_down == 12)
	{
		seg_mode = !seg_mode;
					
	}
	//参数模式
	if(seg_mode)
	{
		if(key_down == 16)
		{
			set_num+=5;
			if(set_num == 95)set_num = 0;
		}	
		if(key_down == 17)
		{
			set_num-=5;
			if(set_num == -5)set_num = 90;
		}
	}
	//L1 L2
	l_data = l_data & 0xfc | (0x01<<seg_mode);	
}
void Init()
{
	seg_mode = 0;
	set_num = 65;
}

三、外设:

#ifndef DEVICE_H
#define DEVICE_H

#include "Public.h"

void All_Close();
void SEG_TSL(u8 *input,u8 *output);
void SEG_Show(u8 COD,u8 PSI);
void Timer1Init(void);		//1毫秒@12MHz
u8 M_Key();
void LED_Show(u8 l_data);
#endif
#include "Device.h"
code unsigned char Seg_Table[] =
{
0xc0,
//0
0xf9,
//1
0xa4,
//2
0xb0,
//3
0x99,
//4
0x92,
//5
0x82,
//6
0xf8,
//7
0x80,
//8
0x90,
//9
0x88,
//A
0x83,
//b
0xc6,
//C
0xa1,
//d
0x86,
//E
0x8e
//F
};

/*
	关闭无关设备
*/
void All_Close()
{
	//关闭蜂鸣器和继电器
	P0 = 0x00;
	P2 = P2 & 0x1f | (0x05<<5);
	P2 &= 0x1f;	
	//关闭LED
	P0 = 0xFF;
	P2 = P2 & 0x1f | (0x04<<5);
	P2 &= 0x1f;
	//关闭数码管
	P0 = 0xFF;
	P2 = P2 & 0x1f | (0x07<<5);
	P2 &= 0x1f;
}

/*
	输入字符串,输出数码管代码
*/
void SEG_TSL(u8 *input,u8 *output)
{
	u8 i=0,j=0;
	for(i=0;i<8;i++,j++)
	{
		switch(input[j])
		{
			case '0':output[i] = Seg_Table[0];break;
			case '1':output[i] = Seg_Table[1];break;
			case '2':output[i] = Seg_Table[2];break;
			case '3':output[i] = Seg_Table[3];break;
			case '4':output[i] = Seg_Table[4];break;
			case '5':output[i] = Seg_Table[5];break;
			case '6':output[i] = Seg_Table[6];break;
			case '7':output[i] = Seg_Table[7];break;
			case '8':output[i] = Seg_Table[8];break;
			case '9':output[i] = Seg_Table[9];break;	
			case 'U':output[i] = ~0x3e;break;	
			default:output[i] = 0xff;
		}
		if(input[j+1] == '.')
		{
			output[i] &= ~0x80;
			j++;	
		}
	}
}

/*
	数码管显示函数
*/
void SEG_Show(u8 COD,u8 PSI)
{
	//消隐
	P0 = 0xff;
	P2 = P2 & 0x1f | (0x07<<5);
	P2 &= 0x1f;	
	//位选
	P0 = 0x01<<PSI;
	P2 = P2 & 0x1f | (0x06<<5);
	P2 &= 0x1f;
	//段选
	P0 = COD;
	P2 = P2 & 0x1f | (0x07<<5);
	P2 &= 0x1f;
}

/*
	定时器1
*/
void Timer1Init(void)		//1毫秒@12MHz
{
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x20;		//设置定时初值
	TH1 = 0xD1;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
	ET1 = 1;
	EA = 1;
}

/*
	矩阵按键按键检测
*/
u8 M_Key()
{
	u16 key_temp=0;
	u8 i=0;
	//置0检测
	P44=0;P42=1;P35=1;P34=1;
	key_temp |= (P3 & 0x0f);
	P44=1;P42=0;P35=1;P34=1;
	key_temp = (key_temp<<4) | (P3 & 0x0f);
	P44=1;P42=1;P35=0;P34=1;
	key_temp = (key_temp<<4) | (P3 & 0x0f);
	P44=1;P42=1;P35=1;P34=0;
	key_temp = (key_temp<<4) | (P3 & 0x0f);


	//对每一位进行0检测
	for(i=0;i<16;i++)
		if((key_temp & (0x8000>>i)) == 0)
			return i+4;
	return 0;
}

/*
	LED显示函数,1为亮
*/
void LED_Show(u8 l_data)
{
	P0 = ~l_data;
	P2 = P2 & 0x1f | (0x04<<5);
	P2 &= 0x1f;	
}

四、串口:

#ifndef UART_H
#define UART_H

#include "Public.h"
#include "stdio.h"


void UartInit(void);	//9600bps@12MHz


#endif
#include "Uart.h"

/*	
	初始化串口
*/
void UartInit(void)		//9600bps@12MHz
{
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x01;		//串口1选择定时器2为波特率发生器
	AUXR |= 0x04;		//定时器2时钟为Fosc,即1T
	T2L = 0xC7;		//设定定时初值
	T2H = 0xFE;		//设定定时初值
	AUXR |= 0x10;		//启动定时器2
	ES = 1;
	EA = 1;
}

/*
	重定义printf为串口发送
*/ 
char putchar (char c)
{
	SBUF = c;
	while(!TI);
	TI = 0;
	return c;
}



五、IIC

#ifndef IIC_H
#define IIC_H

#include "Public.h"

sbit sda = P2^1;
sbit scl = P2^0;

u8 PCF8591_ADC();
void PCF8591_DAC(float volt);
#endif
#include "iic.h"
#define DELAY_TIME	5

//
static void I2C_Delay(unsigned char n)
{
    do
    {
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();		
    }
    while(n--);      	
}

//
void I2CStart(void)
{
    sda = 1;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 0;
	I2C_Delay(DELAY_TIME);
    scl = 0;    
}

//
void I2CStop(void)
{
    sda = 0;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 1;
	I2C_Delay(DELAY_TIME);
}

//
void I2CSendByte(unsigned char byt)
{
    unsigned char i;
	
    for(i=0; i<8; i++){
        scl = 0;
		I2C_Delay(DELAY_TIME);
        if(byt & 0x80){
            sda = 1;
        }
        else{
            sda = 0;
        }
		I2C_Delay(DELAY_TIME);
        scl = 1;
        byt <<= 1;
		I2C_Delay(DELAY_TIME);
    }
	
    scl = 0;  
}

//
unsigned char I2CReceiveByte(void)
{
	unsigned char da;
	unsigned char i;
	for(i=0;i<8;i++){   
		scl = 1;
		I2C_Delay(DELAY_TIME);
		da <<= 1;
		if(sda) 
			da |= 0x01;
		scl = 0;
		I2C_Delay(DELAY_TIME);
	}
	return da;    
}

//
unsigned char I2CWaitAck(void)
{
	unsigned char ackbit;
	
    scl = 1;
	I2C_Delay(DELAY_TIME);
    ackbit = sda; 
    scl = 0;
	I2C_Delay(DELAY_TIME);
	
	return ackbit;
}

//
void I2CSendAck(unsigned char ackbit)
{
    scl = 0;
    sda = ackbit; 
	I2C_Delay(DELAY_TIME);
    scl = 1;
	I2C_Delay(DELAY_TIME);
    scl = 0; 
	sda = 1;
	I2C_Delay(DELAY_TIME);
}

/*
	读取RB2输出电压
*/
u8 PCF8591_ADC()
{
	u8 adc_temp=0;
	//选择PB2通道
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x43);	
	I2CWaitAck();
	
	//读取电压
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	adc_temp = I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	return adc_temp;
}

/*
	写入数据寄存器,输出相应的电压值
*/
void PCF8591_DAC(float volt)
{
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x43);	
	I2CWaitAck();
	I2CSendByte((u8)(volt*255/5));
	I2CWaitAck();
	I2CStop();	
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值