⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 LED的逆向应用:触摸感应-11.9M.zip
💻 C
字号:
#include 	<avr/io.h>
#include	<util/delay.h>
#include	<avr/interrupt.h>
#include	"LightTalk2.h"

#include	<avr/eeprom.h>

#define MER_SWC_NUM		5	/*  水银开关切换几次(延时判断去毛刺)*/
#define	DE_BURR_CNT		5	/* 水银开关检测(毛刺)周期 */
struct {
	unsigned merSwitch	:	1;//水银开关状态位 	1 切换中	0 显示中
	unsigned deBurring	:	1;//去毛刺检测位	1 延时完成	0 延时中		
	unsigned left2right	:	1;//显示方向标志位	1 左->右	0 右->左
	unsigned printLeds	:	1;//显示延时位		1 显示新led	0 现实中
	unsigned periodNew	:	1;//摇动周期更新位	1 更新		0 未更新
}SYSFLAG;
unsigned char gLedsPeriod = 0;//leds输出周期
unsigned char g_timeLedsMS =0;//led显示时间
unsigned char gDeburrCnt = 0;//水银开关(毛刺)检测周期
unsigned char gShakePeriod = 0;//摇动周期
#define	LINE_NUM	32
INT2CHAR gDotArr[LINE_NUM];
//T/C1 中断例程
volatile unsigned int gT1CountMS=0;//1ms计时
SIGNAL(TIMER1_COMPA_vect)
{
	gT1CountMS++;
	g_timeLedsMS++;
	gDeburrCnt++;
	if(gDeburrCnt > DE_BURR_CNT)/* 水银开关(毛刺)检测周期 */
	{	gDeburrCnt=0;
		SYSFLAG.deBurring = 1;/* 微动开关检测 开 */
	}
	if(g_timeLedsMS >= gLedsPeriod)/* leds输出周期 gLedsPeriod = gShakePeriod/LINE_NUM*/
	{	g_timeLedsMS = 0;
		SYSFLAG.printLeds = 1;
	}
	if(SYSFLAG.merSwitch == 1)/* 摇动周期 */
	{	gShakePeriod = gT1CountMS;
		gT1CountMS = 0;
		SYSFLAG.periodNew = 1;/* 保证数据的原子性 */
	}/*记录两次方向切换之间的时间<65536ms*/
}
void delayMs(int i)
{
	for(;i>0;i--)
		_delay_ms(1);
}
/*
*
*	程序名称:整型I16,转成位bit发送
*   输入参数:无符号整型I16
*	输出参数:无,{向串口输出16bit字符,显示输入的整型数}
*   注意事项:需要软串口支持【扩展:返送函数可以改进成程序指针】
*             lightTalk2.c->suart_Byte(x);
*/
void suartInt2bitPrint(unsigned int i16)
{	unsigned char i = 16;
		suart_Byte('b');
	while(i--)
	{
		if(i16 & 0x8000)
		{
			suart_Byte('1');
		}else
		{
			suart_Byte('0');
		}		
		i16<<=1;
	}
	suart_Byte('\n');
	suart_Byte('\r');
}

/*
*
*	程序名称:周期读引脚电平值(低电平为真)(ledtouch,lighttalk2电路支持)
*	入口参数:引脚端口地址【绝对地址,几PORTD等】
*			  (*(volatile unsigned char *)(addrPin))
*	出口参数:无符号字节(端口值,1白,0黑)
*	注意事项:需计时器0 US 延时支持.
*			  LightTalk2.h->_runTimer0_TimeUS(x)....
*
*			  原意是通过硬件计时监测放电周期,结果
*			  程序效果介于延时判断和周期检测方式合并,还可以优化,减少检测
*             时间。(×原理还需细化×)
*/
#define RD_PINS_TIME	7  /* 读端口次数,如果有效值大于一半,则为读取到真 */
unsigned char ReadPinsAsLowInTimePeriod(unsigned int addrPin) 
{	unsigned char i;
	unsigned char RdVal[RD_PINS_TIME]={0};
	unsigned char bitShift=0x01;
			unsigned char bitStore=0;
			unsigned char bit1Cnt=0;
	for(i = 0 ; i < RD_PINS_TIME ; i++)
	{	_runTimer0_TimeUS(180);
		do
		{	_breakTimer0OV();
			RdVal[i] = (*(volatile unsigned char *)(addrPin));
			/*通过SRAM绝对地址读取端口,程序可扩展*/
		}while(  !(RdVal[i] == 0xFF) );/*_breakTimer0OV() 读取引脚1,检测到高电平 下一步*/
		/* 开始新检测周期 */
		_runTimer0_TimeUS(170);
		do
		{	RdVal[i] = (*(volatile unsigned char *)(addrPin));
			
			if( !(RdVal[i] == 0xFF) )/* 读取引脚0,检测到低电平 */
			{
				break;
			}
	
		}_whileTimer0OV();
		_stopTimer0();

	}
  	/* 结算采样数组,有效次数大于等于总采样数,*/
	    /*   则为采样到亮点 1,否则黑点 0          */
	for(char j=0;j<8;j++)
	{
		for(i = 0;i < RD_PINS_TIME;i++)
		{
			if( (RdVal[i] & bitShift ) == 0){bit1Cnt++;}
		}
		if(bit1Cnt >= (RD_PINS_TIME/2))bitStore |= bitShift;
		bit1Cnt=0;
		bitShift<<=1;
	}
	return bitStore;
}
/*
*
*	程序名称:读取led组值(ledtouch,lighttalk2)
*	入口参数:无
*	出口参数:无
*	注意事项:需端口操作宏;Timer0硬件us查询延时支持
*			  LightTalk2.h->_ledsAnode_High(LEDS0);// 阳极 
*							_ledsCathode_ChangeToOutputLow(LEDS0);// 阴极
*							.......
*							_runTimer0_TimeUS(250);.......
*							typedef struct INT2CHAR;//整型<->字节2
*			  U8 ReadPinsAsLowInTimePeriod(U16); 
*			  suartInt2bitPrint(U16);
*             
*
*/

void readLeds(INT2CHAR *I2Cptr)
{	
	INT2CHAR i2cVal;

	/********************************************************/
	/* ISP有影响,除去下载线,效果ok */
	/* 开背景光 Turn ON*/
	_ledsAnode_High(LEDS0);/* 阳极 */
	_ledsCathode_ChangeToOutputLow(LEDS0);/* 阴极 */
	/* 反向偏执 充电 */
	_ledsAnode_Low(LEDS1);
	_ledsCathode_ChangeToOutputHig(LEDS1);
		_runTimer0_TimeUS(250);
	_waitTimer0OV();
	/* 反向偏执 检测光 */
	_ledsCathode_ReadIO_Hi_Z(LEDS1);
	_runTimer0_TimeUS(250);
	_waitTimer0OV();
	_runTimer0_TimeUS(250);
	_waitTimer0OV();

	i2cVal.i8[0]=ReadPinsAsLowInTimePeriod(LEDS1ADDR);

	_ledsAnode_Low(LEDS0);/* 阳极 Turn OFF*/
	_ledsCathode_ChangeToOutputHig(LEDS0);/* 阳极 */
		
/********************************************************/
	/* ISP有影响,除去下载线,效果ok */
	/* 开背景光 Turn ON*/
	_ledsAnode_High(LEDS1);/* 阳极 */
	_ledsCathode_ChangeToOutputLow(LEDS1);/* 阴极 */
	/* 反向偏执 充电 */
	_ledsAnode_Low(LEDS0);
	_ledsCathode_ChangeToOutputHig(LEDS0);
	_runTimer0_TimeUS(250);
	_waitTimer0OV();
	/* 反向偏执 检测光 */
	_ledsCathode_ReadIO_Hi_Z(LEDS0);
	_runTimer0_TimeUS(250);
	_waitTimer0OV();
	_runTimer0_TimeUS(250);
	_waitTimer0OV();

	i2cVal.i8[1]=ReadPinsAsLowInTimePeriod(LEDS0ADDR);

	_ledsAnode_Low(LEDS1);/* 阳极 Turn OFF*/
	_ledsCathode_ChangeToOutputHig(LEDS1);/* 阳极 */
	_ledsCathode_ChangeToOutputHig(LEDS0);/* 复位为输出 */
		
	I2Cptr->i16 = valPack(i2cVal);
	//c2iVal.i16 = valPack(i2cVal);
	//suartInt2bitPrint(c2iVal.i16);
}



int main(void)
{	
	unsigned char i='0',gCnt=0;
	char mercurySwitch = 0;//水银开关状态变换计数(去毛刺)


	unsigned int bitShift=0x0001;
	iniLeds();

	for(i=0;i<LINE_NUM;i++)
	{
		gDotArr[i].i16=~bitShift;
		bitShift<<=1;
		if(bitShift == 0)bitShift = 0x0001;
		ledsTurnOn(valUnPack(gDotArr[i].i16));
	
		_runTimer1_TimeMS(10);
		_waitTimer1OV();
		_stopTimer1();
	}
	

	for(i='0';i<'9';i++)
		suart_Byte(i);
	if(_rdKey(LOOPCTRL) == 0)
	{
		SYSFLAG.left2right = 0;
		gCnt = 32;
	}else
	{
		SYSFLAG.left2right = 1;
		gCnt = 0;
	}
	SYSFLAG.merSwitch = 0;
	SYSFLAG.periodNew = 0;
	SYSFLAG.deBurring = 0;

	gT1CountMS = 0;
	g_timeLedsMS = 0;
	gLedsPeriod = 20;

	_runTimer1CTC(124);/* CTC -> 124等于1ms */
	sei();

 	while(1)
	{	
		if(_rdKey(STARTKEY) == 0)
		{
			for(i=0;i<32;i++)
			{	readLeds(&gDotArr[i]);
				delayMs(150);
			}
		}

		/* 水银开关反转 */
		if(SYSFLAG.deBurring == 1)/* 水银开关(毛刺)检测周期 */
		{	if(_rdKey(LOOPCTRL) == 0)
			{	if(SYSFLAG.left2right == 1)/* 0 -> 1, 计数,去毛刺后,标志置位 */
				{	mercurySwitch++;	/* 取毛刺计时 */
					if(mercurySwitch > (MER_SWC_NUM))
					{	mercurySwitch=0;
						SYSFLAG.left2right= 0;
						SYSFLAG.merSwitch = 1;
					}

				}else/* 未在指定时间内完成,则次数归零 */
				{
					mercurySwitch=0;
				}/* 按键0状态1(按键1状态0),启动切换毛刺计,如果在完成计时前 
					变成按键0状态0(按键1状态1)显示状态,则复位
				*/
			
			}else
			{	if(SYSFLAG.left2right == 0)/* 1 -> 0, 计数,去毛刺后,标志置位 */
				{	mercurySwitch++;
					if(mercurySwitch > (MER_SWC_NUM))//< (char)(0-(MER_SWC_NUM/2)))
					{	mercurySwitch=0;
						SYSFLAG.left2right = 1;
						SYSFLAG.merSwitch = 1;
					}
				}else/* 未在指定时间内完成,则次数归零 */
				{	mercurySwitch=0;
				}

			}
			SYSFLAG.deBurring = 0;
		}
		/* 显示区 */
		if(SYSFLAG.merSwitch == 1)
		{	if(SYSFLAG.periodNew == 1)/* 状态切换中,且周期已更新(保持原子性,在计时1中断内更新) */
			{	SYSFLAG.periodNew = 0;
				suart_Byte('0'+SYSFLAG.left2right);
				SYSFLAG.merSwitch = 0;/* 状态复位(显示状态) *//* 改进:摇臂周期需改进成几次求平均值 */
				gLedsPeriod = gShakePeriod / (LINE_NUM + 5) ;/* 通过摇臂周期计算显示周期 */
				suart_Byte('0'+gShakePeriod/100);	gShakePeriod%= 100;
				suart_Byte('0'+gShakePeriod/10);	gShakePeriod%= 10;
				suart_Byte('0'+gShakePeriod);		gShakePeriod = 0;
				suart_Byte('\n');suart_Byte('\r');
			//	if(SYSFLAG.left2right == 1)/* 初始换显示zhi,方向 */
			//	{
			//		gCnt =0;
			//	}else
			//	{	gCnt =LINE_NUM-1;
			//	}
			}
		}else
		{/* 显示状态 */
			if(SYSFLAG.printLeds == 1)/* 显示Leds */
			{	SYSFLAG.printLeds = 0;
				if((SYSFLAG.left2right == 1) && (gCnt < 32-1))/* 分方向显示,超出范围不显示? */
				{
					ledsTurnOn(valUnPack(gDotArr[gCnt++].i16));
				}else if((SYSFLAG.left2right ==0) && (gCnt > 0))
				{	ledsTurnOn(valUnPack(gDotArr[gCnt--].i16));
				}/* 改进:需加入空区域回显,使得边界变化更好 */
				else
				{
					_ledsAnode_Low(LEDS0);
					_ledsAnode_Low(LEDS1);
					LEDS0VAL	=	0xff;
					LEDS1VAL	=	0xff;
				}
				
			}
		}

	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -