蓝桥杯单片机第11届-电压采集计数

题目

在这里插入图片描述
在这里插入图片描述

mian.c

#include<stc15f2k60s2.h>
#include <intrins.h>

#define uchar unsigned char
#define uint  unsigned int

int   read_vol( );
uchar read_vre(unsigned char add);
void write_vre(uchar add, uchar dat);

#define s0 0x00
#define s1 0x01
#define s2 0x02
uchar state = s0;
uchar disstate = s0;
uchar count_state = s0;
uchar led_state = s0;
uint  count_error = 0;
//uchar keymap[4][4] = {{0x81, 0x41, 0x21, 0x11}, {0x82, 0x42, 0x22, 0x12}, {0x84, 0x44, 0x24, 0x14}, {0x88, 0x48, 0x28, 0x18}};
char  vre;
uint  vol;
uchar count_negedge = 0;

uchar semg_bit[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
uchar semg[14] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90,
								 0xc1, 0x8c, 0xab, 0xff};
uchar semg_temp[8] = {13, 13, 13, 13, 13, 13, 13, 13};


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


void display()
{
	int i;
	
	P0 = 0xff; P2 = 0xc0;
	_nop_();_nop_();
	P0 = 0xff; P2 = 0xe0;
	_nop_();_nop_();
	P2 = 0x00;
	if( (disstate == s0) || (disstate == s1) )
	{
		if(i == 5) 		{P2 = 0xe0; P0 = semg[semg_temp[i]] & 0x7f;}
		else       		{P2 = 0xe0; P0 = semg[semg_temp[i]];}
		P2 = 0xc0; P0 = semg_bit[i]; 
	}
	else
	{
		if(i == 5) 		
		{
			if(semg_temp[i] == 0)	{P2 = 0xe0; P0 = semg[13];}
			else       					  {P2 = 0xe0; P0 = semg[semg_temp[i]];}
		}
		else                    {P2 = 0xe0; P0 = semg[semg_temp[i]];}
		P2 = 0xc0; P0 = semg_bit[i]; 
	}
  P2 = 0x00; P0 = 0xff;
	//_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
	i++;
	if(i == 8)	i = 0;
}


void led()
{
	static int time_count = 0;
	 P0 = 0xff; P2 = 0x80;
	_nop_();_nop_();
	
	switch(led_state)
	{
		case	s0:								//等待Vin < vp的时间大于等于5秒,实际上等于5秒时就应该进入s1
		{	
			if(vol < vre * 10)
			{
				time_count++;
				if(time_count == 500*5)
					led_state = s1;
				else
					led_state = s0;
			}
			else
			{
				led_state = s0;
				time_count = 0;
			}
		}	break;
		case	s1:											//vin < vp时间大于等于5秒,点亮led1, 同时等待vin < vp将led1熄灭
		{	
			if(vol >= vre * 10)
			{
				led_state = s0;
				time_count = 0;
				P2 = 0x80;	P00 = 0;
			}
			else
			{
				led_state = s1;
				P2 = 0x80;	P00 = 0;
			}
		}	break;
		default:	led_state = s0; break;
	}
	
	if(count_negedge % 2 == 1)	{P2 = 0x80; P01 = 0;}
	else												{P2 = 0x80; P01 = 1;}
	
	if(count_error >= 3)	{P2 = 0x80; P02 = 0;}
	else									{P2 = 0x80; P02 = 1;}
	P2 = 0x80; P0 = P0 | 0xf8;
	//_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
	P2 = 0x00; P0 = 0xff;
}


void display_led() interrupt 1
{
	uchar i;
	if(i == 50)
	{
		vol = read_vol();
		i = 0;
	}
	led();
	display();
	i++;
}


char keybordscan()
{
  uchar keyrow, keycolumn, keycode;
	char keyvalue_temp, i, j;
	static char  keyvalue = -10,keystate = s0;
	
	P44 = 0;P42 = 0;P3 = 0x0f;
	keycolumn = P3 & 0x0f;
	
	P44 = 1;P42 = 1;P3 = 0xf0;
	if(!P44)						keyrow = 0x70;
	else if(!P42)				keyrow = 0xb0;
	else if(P3!=0xf0)   keyrow = P3 & 0xf0;
	else                keyrow = 0xf0;
	
	keycode = ~(keycolumn | keyrow);
	
	switch(keystate)
	{
		case s0:	
			if(keycode)	
				keystate = s1;
			else
				keyvalue = -10;
			break;
				
		case s1:	
		{
			if(keycode)
			{
				for(i = 0; i<4; i++)
					for(j = 0; j<4; j++)
						if( keycode == ( (0x80>>j) | (0x01<<i) ) )	
						{
							keyvalue_temp = i*4 + j;
							keyvalue = keyvalue_temp;
							break;
						}
						else ;
				keystate = s2;
			}
			else
				keystate = s0;
		}	break;
		
		case s2:	
		{
			keyvalue = -10;
			if(!keycode)	keystate = s0;
			else          keystate = s2;
		}	break;
		default:
			keystate = s0;
			break;
	}
	//semg_temp[2] = (keyvalue + 10) / 10;
	//semg_temp[3] = (keyvalue + 10) % 10;
	return keyvalue;
}


void counter_negedge( )
{
	//semg_temp[2] = vol/100;
	//semg_temp[3] = (vol - semg_temp[2] * 100)/10;
	//semg_temp[4] = vol % 10;
	switch(count_state)
	{
		case s0:
		{
			if(vol <= vre * 10)
				count_state = s0;
			else									//测得电压vin大于参考电压vp,进入S1状态,等待测得电压Vin小于vp
				count_state = s1;
		}	break;
		
		case s1:
		{
			if(vol >= vre * 10)		
				count_state = s1;
			else								//s1状态测得电压vin小于参考电压vp,计数值加一,回到S0状态
			{
				count_negedge++;
				count_state = s0;
			}
		}	break;
		
		default:	count_state = s0;	break;
	}
	
}


void menu(char keyvalue)
{
	switch(state)
	{
		case s0:												//测电压界面,显示在定时器0
		{
			semg_temp[0] = 10;
			semg_temp[5] = vol/100;
			semg_temp[6] = (vol - semg_temp[5] * 100)/10;
			semg_temp[7] = vol % 10;
			if(keyvalue == 14)
			{
				disstate = s1;
				state = s1;
				count_error = 0;
			}
			else if( (keyvalue != 14) && (keyvalue != -10) )
				count_error++;
			else	;
		}	break;
		
		case s1:										//修改参考电压界面,显示在定时器0
		{
			semg_temp[0] = 11;
			semg_temp[5] = vre/10;
			semg_temp[6] = vre % 10;
			semg_temp[7] = 0;
			
			if(keyvalue == 14)	
			{
				disstate = s2;
				state = s2;
				count_error = 0;
				write_vre(0, vre);
			}
			else if(keyvalue == 15)	
			{	
				vre = vre + 5;
				if(vre > 50)
					vre = 0;
				count_error = 0;
				write_vre(0, vre);
			}
			else if(keyvalue == 11)	
			{	
				vre = vre - 5;
				if(vre < 0)
					vre = 50;
				count_error = 0;
				write_vre(0, vre);
			}
			else if( (keyvalue != -10) && (keyvalue != 11) && (keyvalue != 14) && (keyvalue != 15) )
				count_error++;
			else	;
		}	break;
		
		case s2:									//计数界面,显示在定时器0
		{
			semg_temp[0] = 12;
			semg_temp[5] = count_negedge/100;
			semg_temp[6] = (count_negedge - semg_temp[5] * 100)/10;
			semg_temp[7] = count_negedge % 10;
			counter_negedge( );			
			if(keyvalue == 10)	
			{
				count_negedge = 0;
				count_error = 0;
			}
			else if(keyvalue == 14)	
			{
				disstate = s0;
				state = s0;
				count_error = 0;
			}
			else if( (keyvalue != -10) && (keyvalue != 10) && (keyvalue != 14) )
				count_error++;
		}	break;
		
		default:	
		{
			disstate = s0;
			state = s0;
		}	break;
	}
}


void init_all()
{
	P2 = 0xc0; P0 = 0xff;
	P2 = 0xe0; P0 = 0xff;
	P2 = 0xa0; P0 = 0x00;
	P2 = 0x80; P0 = 0xff;
}


void main()
{
	char keyvalue;
	init_all();
	Timer0Init();
	vre = read_vre(0);
	if( (vre % 5 != 0) || (vre > 50) || (vre < 0) )
		vre = 30;
	while(1)	
	{
		keyvalue = keybordscan();
		menu(keyvalue);
	}
}

IIC.c

/*
  程序说明: IIC总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include<stc15f2k60s2.h>
#include "intrins.h"


#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}    
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//总线引脚定义
sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */


void IIC_Start(void)
{
	SDA = 1;
	SCL = 1;
	somenop;
	SDA = 0;
	somenop;
	SCL = 0;	
}


void IIC_Stop(void)
{
	SDA = 0;
	SCL = 1;
	somenop;
	SDA = 1;
}


bit IIC_WaitAck(void)
{
	SDA = 1;
	somenop;
	SCL = 1;
	somenop;
	if(SDA)    
	{   
		SCL = 0;
		IIC_Stop();
		return 0;
	}
	else  
	{ 
		SCL = 0;
		return 1;
	}
}


void IIC_SendByte(unsigned char byt)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{   
		if(byt&0x80) 
		{	
			SDA = 1;
		}
		else 
		{
			SDA = 0;
		}
		somenop;
		SCL = 1;
		byt <<= 1;
		somenop;
		SCL = 0;
	}
}


unsigned char IIC_RecByte(void)
{
	unsigned char da;
	unsigned char i;
	
	for(i=0;i<8;i++)
	{   
		SCL = 1;
		somenop;
		da <<= 1;
		if(SDA) 
		da |= 0x01;
		SCL = 0;
		somenop;
	}
	return da;
}


void write_vre(unsigned char add,unsigned char dat)
{
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_SendByte(dat);	
  IIC_WaitAck();
	IIC_Stop();
}


unsigned char read_vre(unsigned char add)
{
	unsigned char dat;
	
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0xa1);
	IIC_WaitAck();
	dat=IIC_RecByte();	
  IIC_Stop();
	return dat;

}


int read_vol( )
{
	int dat;
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x03);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	dat=IIC_RecByte();	
  IIC_Stop();
	dat=dat*1.96078;
	return dat;
}
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值