📄 main.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 + -