2020-11-13

@**[蓝桥杯](单片机设计组第十届省赛)

这是我写的第一篇文章,不好的地方还请大家见谅,有什么问题欢迎评论留言,共同学习共同进步~
说明
本次省赛涉及到 PCF8591的AD和DA功能,测量RB2(对应通道3)的电压,NE555测频功能,使用T0作为计数器,使用定时器T1产生1s的门控信号,对NE555的输出SIGNAL进行计数,完成频率测量。

程序设计题目:

历年省赛试题
提取码:asdf

代码:

1 、main.c

#include "STC15F2K60S2.H"
#include "key.h"
#include "iic.h"

#define u8 unsigned char
#define u16 unsigned int
/**********
函数声明
*******/
void system_init();
void count_0_init();
void timer_1_init();
void smg_display(unsigned char what[]);
void key_processing();
void led_processing();


/**************
变量定义
************/
u8 code smg_duan[]={                       //标准字库
//   0    1    2    3    4    5    6    7    8    9    
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,
	0xBF,0X86,0XDB,0XCF,0XE6,0XED,0XFD,0X87,0XFF,0XEF,0X40,0X00,0X71,0X3E };
//	 0.   1.   2.   3.   4.    5.   6.   7.   8.   9.   -	 灭	  F	   U

u8 code smg_wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //位码   0111 0001



u8 smg_buff[8];
u8 frequency_array[8] = {22,21,21,21,21,21,21,21};
u8 voltage_array[8] = {23,21,21,21,21,21,21,21};

bit count_10ms_flag = 0 , adc_flag = 0 ,led_EN = 0 ,smg_EN = 0 ,DA_index = 0;

u8 key_vaule = 0 ;
u16 adc_vaule = 0 ;
u8 menu_index = 1 ;
u16 frequency_count = 0;
u16 frequency = 0 ;


/******
主程序
************/
void main()
{
	system_init(); 
	count_0_init();
	timer_1_init();	//   1 ms
	while(1)
	{
		if(adc_flag == 1)
		{
			adc_flag = 0 ;

			adc_vaule = (u16)(read_adc(0x03) * 1.917) ;	 //   1 / 255  * 4.89 * 100 = 1.917  :-->数字0~255转化为电压 0~489 单位 0.01V

			voltage_array[5] = 	adc_vaule / 100 + 10; // 带小数点的 adc_vaule 的百位
			voltage_array[6] = 	adc_vaule / 10 % 10 ;
			voltage_array[7] = 	adc_vaule % 10 ;
		


			if(DA_index == 0) // 固定 DAC  2.0 V
			{
				write_dac((2.0+0.05)*51); 
			}
			else	 //  跟 随 A D 输出 
			{
				if(( adc_vaule + 2 ) * 0.521 > 255)
					write_dac(255); 
				else
					 write_dac(( adc_vaule + 2 )  * 0.521 );
			}

			led_processing();
			 
		}

		key_processing();
	}
}
/*******
	计 数  器 0 中 断 服务 子 程 序
**********/
void count_0_INT_processing() interrupt 1
{
	frequency_count++;	
}
/*******
	定 时 器 1 中 断 服务 子 程 序
**********/
void timer_1_INT_processing() interrupt 3
{
	static int count_2ms = 0 , count_10ms = 0 , count_1000ms = 0 ;
	u8 dat_index = 0 ;

	count_2ms++; count_10ms++;	 count_1000ms++;
	if(count_2ms == 2)
	{
		count_2ms = 0 ;

		smg_display(smg_buff);  //  调 用 显 示 子 程 序	
	}
	if(count_10ms == 10)
	{
		count_10ms = 0 ;
		count_10ms_flag = 1 ;
		adc_flag = 1 ;
	}
	if(count_1000ms == 1000)
	{
		count_1000ms = 0 ;
		TR0 = 0 ;
		ET0 = 0 ;
		frequency =  frequency_count ;
		frequency_array[2] =  frequency_count / 100000 ;
		frequency_array[3] =  frequency_count / 10000 % 10 ;
		frequency_array[4] =  frequency_count / 1000 % 10 ;
		frequency_array[5] =  frequency_count / 100 % 10 ;
	   	frequency_array[6] =  frequency_count / 10 % 10 ;
		frequency_array[7] =  frequency_count % 10 ;
	    dat_index = 2 ;
		while(frequency_array[dat_index] == 0)
		{
			frequency_array[dat_index] = 21 ;
			dat_index ++ ;		
		}
		frequency_count = 0 ;
		ET0 = 1 ;
		TR0 = 1 ;
			
	}
		
}
/*********************
*******显示子程序 ****
*******           ******
*********/
void smg_display(u8 what[])
{
	static int where = 0 ;

	u8 i = 0 ;
	for(i = 0 ; i < 8 ; i++)
	{
		if(smg_EN == 1)
		{
			switch(menu_index)
			{
				
				case(1): what[i] = ~smg_duan[voltage_array[i]] ;break ;
				case(2): what[i] = ~smg_duan[frequency_array[i]] ;break ;
			}
		}
		else
		{
			what[i] = ~smg_duan[21];	
		}
	}
	
	P2 = 0X00 ; P0 = 0x00 ; P2 = 0XC0 ;
	P2 = 0X00 ; P0 = smg_wei[where] ; P2 = 0XC0 ;
	P2 = 0X00 ; P0 = what[where]; P2 = 0XE0 ;
	where++;if(where == 8)where = 0 ;

}
/*
********************
******led 子 程 序 ****
************************
*/
void led_processing()
{
	u8 led_return ;
	if(led_EN == 1)
	{
		if(menu_index == 0)led_EN = 0 ;
		else if(menu_index == 1)
		{
			if(DA_index == 0)
			{
				if((adc_vaule < 150) || ( (adc_vaule >= 250) && (adc_vaule < 350 ) ))
					led_return = 0xfe ;
				else
					led_return = 0xfa ;
			}
			else
			{
				if((adc_vaule < 150) || ( (adc_vaule >= 250) && (adc_vaule < 350 ) ))
					led_return = 0xee ;	   
				else
					led_return = 0xea ;	
			}
		}
		else
		{
			if((frequency < 1000) || ( (frequency >= 5000) && (frequency < 10000 ) ))
				led_return = 0xfd; 
			else 
				led_return = 0xf5;
		}

		P2 = 0X00 ; P0 = led_return; P2 = 0x80 ;
	}
	else
	{
		P2 = 0X00 ; P0 = 0xff; P2 = 0x80 ;
	}
}
/*********************
*****按 键 处理 *******
*************
*********/
void key_processing()
{
	if(count_10ms_flag == 1)
	{	
		count_10ms_flag = 0 ;

		key_vaule = key_btn();

		switch(key_vaule)
		{
			case(4):menu_index ++ ;
					if(menu_index ==3)menu_index =1 ;
					 break;
			case(5):DA_index = !DA_index ;
					break;
			case(6):led_EN = !led_EN ;
					break;
			case(7):smg_EN = !smg_EN ;
					break;
		}
	}	
}
/*********************
*****初 始 化 *******
*************
*********/
void count_0_init()
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD = (TMOD & 0XF0) | 0x04;		//设置定时器模式------方式0 计数
	TL0 = 0xff;		//设置定时初值
	TH0 = 0xff;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1 ;
	EA = 1 ;
}
void timer_1_init()	
{
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD = (TMOD & 0X0F) ; 		//设置定时器模式------方式0 计数
	TL1 = 0x20;		//设置定时初值
	TH1 = 0xd1;		//设置定时初值
	TF1 = 0;		//清除TF0标志
	TR1 = 1;		//定时器0开始计时
	ET1 = 1 ;
	EA = 1 ;
}
void system_init()
{
	/*
		注:先将 P2 = 0X00 可以预防在P0口赋值后的相对短的一段时间里
			其他外设的状态发生预期之外的变化
	*/
	P2 = 0X00 ; P0 = 0XFF ; P2 = 0X80;  //  关 闭 led
	P2 = 0X00 ; P0 = 0X00 ; P2 = 0XA0;  //  关 闭 led
}

**

**2 、 key.c

**
这里是独立按键,将板子左下方的J5的跳冒接到BTN模式

#include "key.h"

#define key_state0  0
#define key_state1  1
#define key_state2  2

unsigned char key_btn()
{
	static char key_state = 0;
	unsigned char key_press , key_return = 0 ;
	
	if(P33 == 0) key_press = 0X07 ;
	else if(P32 == 0) key_press = 0X0b ;
	else if(P31 == 0) key_press = 0X0d ;
	else if(P30 == 0) key_press = 0X0e ;
	else key_press = 0x0f ;


	switch(key_state)
	{
		case(key_state0):
			if(key_press != 0x0f)
			{
				key_state = key_state1 ;
			}
			break ;

		case(key_state1):
			if(key_press != 0x0f)
			{
				if(key_press == 0x07)key_return = 4 ;
				else if(key_press == 0x0b)key_return = 5 ;
				else if(key_press == 0x0d)key_return = 6 ;
				else if(key_press == 0x0e)key_return = 7 ;

				key_state = key_state2 ;
			}
			else
			{
				key_state = key_state0 ;
			}

			break ;
		case(key_state2):
			if(key_press == 0x0f)
			{
				key_state = key_state0 ;
			}

			break ;
	}

	return key_return ;
	
}
**

**
**

3、iic.c

**

#include "iic.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;    
}
unsigned char read_adc(unsigned char address)
{
	unsigned char temp = 0 ;

	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(address);
	IIC_WaitAck();

	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();

	temp = IIC_RecByte();

	IIC_Stop();

	return temp ;
}
void write_dac(unsigned char dat)
{
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x40);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

```4 、 头文件

iic.h

#ifndef _IIC_H
#define _IIC_H

#include "STC15F2K60S2.H"
/*
void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendAck(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 
*/
unsigned char read_adc(unsigned char address);
void write_dac(unsigned char dat);

#endif

key.h

#ifndef _KEY_H
#define _KEY_H

#include "STC15F2K60S2.H"

unsigned char key_btn();

#endif
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一个 SQL 语句,用于向借阅表中插入数据。该表包含以下字段:借阅编号、读者编号、书籍编号、借阅日期、归还日期、借阅状态。每条数据表示一次借阅记录。其中借阅编号、读者编号、书籍编号、借阅日期和借阅状态是必填项,归还日期为可选项,如果借阅状态为“已还”则必须填写归还日期。 具体插入的数据如下: - 借阅编号:100001,读者编号:123413,书籍编号:0001,借阅日期:2020-11-05,归还日期:NULL,借阅状态:借阅 - 借阅编号:100002,读者编号:223411,书籍编号:0002,借阅日期:2020-9-28,归还日期:2020-10-13,借阅状态:已还 - 借阅编号:100003,读者编号:321123,书籍编号:1001,借阅日期:2020-7-01,归还日期:NULL,借阅状态:过期 - 借阅编号:100004,读者编号:321124,书籍编号:2001,借阅日期:2020-10-09,归还日期:2020-10-14,借阅状态:已还 - 借阅编号:100005,读者编号:321124,书籍编号:0001,借阅日期:2020-10-15,归还日期:NULL,借阅状态:借阅 - 借阅编号:100006,读者编号:223411,书籍编号:2001,借阅日期:2020-10-16,归还日期:NULL,借阅状态:借阅 - 借阅编号:100007,读者编号:411111,书籍编号:1002,借阅日期:2020-9-01,归还日期:2020-9-24,借阅状态:已还 - 借阅编号:100008,读者编号:411111,书籍编号:0001,借阅日期:2020-9-25,归还日期:NULL,借阅状态:借阅 - 借阅编号:100009,读者编号:411111,书籍编号:1001,借阅日期:2020-10-08,归还日期:NULL,借阅状态:借阅
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值