由上圖可以看出來(lái),EV1527編碼由一個(gè)同步嗎鸽凶,和地址碼還有數(shù)據(jù)碼組成币砂。顧名思義同步碼用于信號(hào)的同步,主要用于校驗(yàn)玻侥,數(shù)據(jù)碼和地址碼共同組成了鍵碼决摧,主要用于區(qū)分各個(gè)按鈕。
然后同步碼總共是4個(gè)周期的高電平和124個(gè)周期的低電平組成凑兰。4個(gè)周期的高電平也就是窄脈寬掌桩,12個(gè)周期的高電平是寬脈寬。
數(shù)據(jù)‘0’由兩個(gè)窄脈寬組成姑食。
數(shù)據(jù)‘1’由兩個(gè)寬脈寬組成波岛。
數(shù)據(jù)‘f’由一個(gè)窄脈寬加一個(gè)寬脈寬組成。
無(wú)效碼由寬脈寬加窄脈寬組成音半。
所以我們的工作是要從解碼開(kāi)始则拷,這里利用單片機(jī)的中斷進(jìn)行脈寬計(jì)數(shù),從而利用Data_dispose()這個(gè)函數(shù)轉(zhuǎn)化成以上的碼位曹鸠。
以下是中斷部分的源代碼:
INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23)
{
/* In order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction.
*/
/*******************************************************************************************/
//LED燈顯示
/*******************************************************************************************/
if(tim_count_on>0) //如果燈計(jì)數(shù)大于零常亮煌茬,無(wú)視閃爍間隔
{
LED_POWER_ON(); //燈點(diǎn)亮
tim_count_on--; //常量計(jì)數(shù)減一
tim_count_fast=0; //LED計(jì)數(shù)
tim_count_normal=0;
tim_count_low=0;
}
else //如果常亮計(jì)數(shù)不大于零,則取消常亮彻桃,恢復(fù)閃爍
{
tim_count_fast++; //LED計(jì)數(shù)
tim_count_normal++;
tim_count_low++;
}
if(tim_count_fast>=TIME_FAST_COUNT)
{
tim_count_fast=0;
if(led_speed==LED_FAST) //快速閃
LED_POWER_OX(); //呼吸燈
}
if(tim_count_normal>=TIME_NORMAL_COUNT)
{
tim_count_normal=0;
if(led_speed==LED_NORMAL) //普通
LED_POWER_OX(); //呼吸燈
}
if(tim_count_low>=TIME_SLOW_COUNT)
{
tim_count_low=0;
if(led_speed==LED_SLOW) //慢閃
LED_POWER_OX(); //呼吸燈
}
/****************************************************************/
/*******************************************************************/
//學(xué)習(xí)按鍵處理
if(STUDY_DATA()==0&&correct_flag==0&&flash_clear==0) //確定不處于數(shù)據(jù)清除狀態(tài)和校正狀態(tài)
{
time_key1_count++;
if(time_key1_count>=60000)
{
time_key1_count=0;
correct_flag=1; //進(jìn)入校正狀態(tài)
}
}
else if(STUDY_DATA()==1&&correct_flag==0&&flash_clear==0)
{
time_key1_count=0;
}
//清除按鍵處理
if(CLEAR_DATA()==0&&correct_flag==0&&flash_clear==0)
{
time_key2_count++;
if(time_key2_count>=60000)
{
time_key2_count=0;
flash_clear=1;
}
}
else if (CLEAR_DATA()==1&&correct_flag==0&&flash_clear==0)
{
time_key2_count=0;
}
/*********************************************************************/
//信號(hào)判斷
/*******************************************************************/
if(EV_1527()!=0) //高電平
{ //step:一個(gè)周期分3個(gè)小段3個(gè)小段決定
high_count++;
if(step==0)
step=1;
if(step==2)
step=3;
}
else if(EV_1527()== 0 ) //低電平
{
low_count++;
if(step==1)
step=2;
}
if((tb_num==0)&&(step==3)) //同步碼沒(méi)接收到宣旱,判斷同步碼
{
step=0;
if((high_count>=L_COUNT&&high_count<=H_COUNT) && (low_count>=L_COUNT_30 &&low_count<=H_COUNT_30))
{
tb_num=1; //同步碼收到,標(biāo)志位=1
}
high_count=0;
low_count=0;
}
else if((tb_num==1)&&(step==3)) //同步碼接受成功并且已收到一段數(shù)據(jù)
{
step=0;
if(high_count>=L_COUNT&&high_count<=H_COUNT && low_count>=L_COUNT_3&&low_count<=H_COUNT_3) //窄
{
if(high_w==0)
{
high_w=1; //窄標(biāo)記
}
else if(high_w!=0)
{
high1_w=1; //窄標(biāo)記
data_flag=1;
}
}
else if(low_count>=L_COUNT&&low_count<=H_COUNT && high_count>=L_COUNT_3&&high_count<=H_COUNT_3) //寬
{
if(high_w==0)
{
high_w=2; //寬標(biāo)記
}
else if(high_w!=0)
{
high1_w=2; //寬標(biāo)記
data_flag=1;
}
}
high_count=0;
low_count=0;
}
TIM4_ClearITPendingBit(TIM4_IT_UPDATE);
}
/**************************************************************************************************************************************************************************************************/
//信號(hào)處理叛薯,將信號(hào)轉(zhuǎn)化為數(shù)據(jù)
void Data_dispose()
{
if(data_flag==1) //脈沖接收成功
{
if(high_w==1&&high1_w==1) //窄脈沖,窄脈沖
{
data[data_count]=0x00; //解碼 00
data_count++;
}
else if(high_w==1&&high1_w==2) //窄寬
{
data[data_count]=0x01; //解碼 01
data_count++;
}
else if(high_w==2&&high1_w==1) //寬窄
{
data[data_count]=0x02; //解碼 10
data_count++;
}
else if(high_w==2&&high1_w==2) //寬寬
{
data[data_count]=0x03; //解碼 11
data_count++;
}
if(data_count>=12) //數(shù)據(jù)接收完為12個(gè)字節(jié)
{
tb_num=0; //同步碼清除
rev_flag=1; //接收數(shù)據(jù)成功
data_count=0; //接收計(jì)數(shù)清除
light_weight(); //數(shù)據(jù)輕量化處理
}
high_w=0; //脈沖清除
high1_w=0;
data_flag=0; //脈沖接收標(biāo)志清除
}
}
/**************************************************************************************************************************************************************************************************/
//接下來(lái)還有數(shù)據(jù)校準(zhǔn)學(xué)習(xí)函數(shù)笙纤,這個(gè)函數(shù)主要用于遙控機(jī)器碼的學(xué)習(xí)耗溜,因?yàn)檫@個(gè)是做產(chǎn)品的,所以//考慮到客戶會(huì)有遙控器丟失或者損壞的情況省容,這種情況下就需要買個(gè)新的遙控器抖拴,并且讓你的機(jī)器//知道并能識(shí)別你新的遙控器的編碼
u8 data_correct(void) //數(shù)據(jù)xuexi
{
led_speed=LED_FAST; //led快速閃動(dòng),證明進(jìn)入學(xué)習(xí)模式
if(data_flag==1) //若收到數(shù)據(jù)
{
if(data_batch<=2) //0~2,3批次數(shù)據(jù)接收
{
if(high_w==1&&high1_w==1) //數(shù)據(jù)解碼
{
data[data_batch*12+data_count]=0x00;
data_count++;
}
else if(high_w==2&&high1_w==2)
{
data[data_batch*12+data_count]=0x03;
data_count++;
}
else if(high_w==1&&high1_w==2)
{
data[data_batch*12+data_count]=0x01;
data_count++;
}
else if(high_w==2&&high1_w==1)
{
data[data_batch*12+data_count]=0x02;
data_count++;
}
if(data_count== 12) //當(dāng)收滿數(shù)據(jù)
{
tb_num=0; //同步碼清零
rev_flag=1; //接受標(biāo)志位置一
data_count=0; //接受數(shù)據(jù)位清零
data_batch++; //進(jìn)入第下批數(shù)據(jù)接受
}
}
high_w=0;
high1_w=0;
data_flag=0;
if(data_batch >= 2 && data_batch<=3 ) //
{
if(strncmp(&data[(data_batch-2)*12],&data[(data_batch-1)*12],12)&&(!strncmp(&data[(data_batch-1)*12],data_0,12))); //判斷第一批和第二批數(shù)據(jù)是否相同腥椒,且不
else //數(shù)據(jù)不相等,則清除阿宅,重新接受校準(zhǔn)
{
data_batch = 0;
memset(&data[0],0,3*12);//data數(shù)據(jù)清除
}
}
if(data_batch>=3) //0,1,2。3批次連續(xù)接收相等笼蛛,證明數(shù)據(jù)穩(wěn)定
{
data_batch=0; //批次歸零
light_weight(); //數(shù)據(jù)輕量化
if(study_step==0)
{
//按鍵0學(xué)習(xí)
strncpy(light_data,&tmp_data_kai_1[0],CONFIG_L); //輕量化數(shù)據(jù)存入臨時(shí)數(shù)據(jù)庫(kù)
memset(&light_data[0],0,CONFIG_L); //數(shù)據(jù)清除
//led_speed=LED_SLOW; //LED顯示快速閃動(dòng)
tim_count_on=TIME_ON_COUNT; //LED常量
delayms(200);
study_step=1; //按鍵1學(xué)習(xí)完畢
}
else if (study_step==1)
{
if(strncmp(light_data,&tmp_data_kai_1[0],CONFIG_L) != 1)
{
strncpy(light_data,&tmp_data_guan_1[0],CONFIG_L); //輕量化數(shù)據(jù)存入臨時(shí)數(shù)據(jù)庫(kù)
memset(&light_data[0],0,CONFIG_L);//data數(shù)據(jù)清除
//led_speed=LED_SLOW; //LED顯示
tim_count_on=TIME_ON_COUNT;
delayms(200);
study_step=2; //按鍵2學(xué)習(xí)完畢
}
}
else if (study_step==2)
{
if((strncmp(light_data,&tmp_data_kai_1[0],CONFIG_L) != 1)&&(strncmp(light_data,&tmp_data_guan_1[0],CONFIG_L) != 1))
{
strncpy(light_data,&tmp_data_kai_2[0],CONFIG_L);
memset(&light_data[0],0,CONFIG_L);//data數(shù)據(jù)清除
//led_speed=LED_SLOW;
tim_count_on=TIME_ON_COUNT; //常亮一秒時(shí)間
delayms(200);
study_step=3; //按鍵3學(xué)習(xí)完畢洒放,按鍵三學(xué)習(xí)完畢
}
}
else if (study_step==3)
{
if((strncmp(light_data,&tmp_data_kai_1[0],CONFIG_L) != 1)&&(strncmp(light_data,&tmp_data_guan_1[0],CONFIG_L) != 1)&&(strncmp(light_data,&tmp_data_kai_2[0],CONFIG_L) != 1))
{
strncpy(light_data,&tmp_data_guan_2[0],CONFIG_L); //按鍵4學(xué)習(xí)完畢
memset(&light_data[0],0,CONFIG_L);//data數(shù)據(jù)清除
strncpy(&tmp_data_kai_1[0],&data_fun_kai[config_data_count][0],CONFIG_L); //學(xué)習(xí)后的數(shù)據(jù)存入臨時(shí)數(shù)組
strncpy(&tmp_data_guan_1[0],&data_fun_guan[config_data_count][0],CONFIG_L);
strncpy(&tmp_data_kai_2[0],&data_shk_kai[config_data_count][0],CONFIG_L);
strncpy(&tmp_data_guan_2[0],&data_shk_guan[config_data_count][0],CONFIG_L);
config_data_count++; //總共遙控器個(gè)數(shù)增加一個(gè)
memset(&tmp_data_kai_1[0],0,CONFIG_L); //臨時(shí)data數(shù)據(jù)清除
memset(&tmp_data_guan_1[0],0,CONFIG_L); //臨時(shí)data1數(shù)據(jù)清除
memset(&tmp_data_kai_2[0],0,CONFIG_L); //臨時(shí)data數(shù)據(jù)清除
memset(&tmp_data_guan_2[0],0,CONFIG_L); //臨時(shí)data1數(shù)據(jù)清除
correct_flag=0; //學(xué)習(xí)標(biāo)志清零
study_step=0; //學(xué)習(xí)步驟清零
write_flag=1; //flash寫入準(zhǔn)備完成 //LED燈常量3秒,表示學(xué)習(xí)完成
tim_count_on=TIME_ON_COUNT; //亮燈計(jì)數(shù)開(kāi)始
delayms(200);
led_speed=LED_SLOW;
}
}
return 1;
}
}
return 0;
}
/**************************************************************************************************************************************************************************************************/
//這一部分就是數(shù)據(jù)輕量化處理:主要用于減少數(shù)據(jù)存在flash內(nèi)所占用的內(nèi)存
//根據(jù)觀察滨砍,上面數(shù)據(jù)總共分4類,0x00,0x01,0x02,0x03
//假設(shè)一個(gè)數(shù)據(jù)[0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03]
//輕量化之前每個(gè)0x03是0b00000011往湿。輕量化以后0x03變成0b11妖异,所以存儲(chǔ)空間節(jié)省為原來(lái)的 // 1/4,最終存儲(chǔ)可以達(dá)到10個(gè)领追,可以滿足產(chǎn)品需求
void light_weight(void)
{
//數(shù)據(jù)壓縮他膳,將數(shù)據(jù)壓縮成3個(gè)字節(jié),釋放存儲(chǔ)空間
light_data[0]=data[0]+data[1]*4+ data[2]*16+ data[3]*64; //
light_data[1]=data[4]+data[5]*4+ data[6]*16+ data[7]*64; //
light_data[2]=data[8]+data[9]*4+ data[10]*16+data[11]*64; //
memset(&data[0],0,3*12);//data數(shù)據(jù)清除
}
/**************************************************************************************************************************************************************************************************/
//以下是存取flash的函數(shù)绒窑,主要用于鍵碼的保存和讀取
void write_config(void)
{
Write_EEPROM();
}
void read_config(void)
{
Read_EEPROM();
}
//------------------------------------------------------------------------------------------------------------
// 名稱: Write_EEPROM 棕孙。
// 功能: 將數(shù)據(jù)寫入到EEPROM中 。
// 調(diào)用:無(wú) 些膨。
// 返回: 無(wú) 蟀俊。
// 說(shuō)明: 無(wú)。
// 形參: 無(wú) 傀蓉。
// 形參取值范圍: 無(wú) 欧漱。
//------------------------------------------------------------------------------------------------------------
void Write_EEPROM(void)
{
u8 i,j;
FLASH_Unlock(FLASH_MEMTYPE_DATA); //EEPROM解除保護(hù)。
for(i=0; i<(4*CONFIG_L*CONFIG_W)+3; i++) //寫入前葬燎,全部擦除误甚。
{
FLASH_EraseByte(EEPROM_HEAD_ADDR + i);
}
//在EEPROM的首地址寫入標(biāo)志字節(jié),表示EEPROM被使用過(guò)谱净,內(nèi)有有效數(shù)據(jù)窑邦。
FLASH_ProgramByte(EEPROM_HEAD_ADDR, FLAG_VALIDDATA);
FLASH_ProgramByte(EEPROM_HEAD_ADDR+1, soft_num); //版本號(hào)
FLASH_ProgramByte(EEPROM_HEAD_ADDR+2, config_data_count);
//將10組共60個(gè)字節(jié)的數(shù)據(jù)寫入EEPROM中。
for(i=0; i<config_data_count; i++)
{
for(j=0; j<CONFIG_L; j++)
{
FLASH_ProgramByte(EEPROM_HEAD_ADDR+3+j+CONFIG_L*i, data_fun_kai[i][j]); //寫入第一組鍵碼值
}
}
for(i=0; i<config_data_count; i++)
{
for(j=0; j<CONFIG_L; j++)
{
FLASH_ProgramByte(EEPROM_HEAD_ADDR+3+(CONFIG_L*CONFIG_W)+j+CONFIG_L*i,data_fun_guan[i][j]); //寫入第二組鍵碼值
}
}
for(i=0; i<config_data_count; i++) //寫入第三組鍵碼值
{
for(j=0;j<CONFIG_L;j++)
{
FLASH_ProgramByte(EEPROM_HEAD_ADDR+3+ 2*(CONFIG_L*CONFIG_W)+j+CONFIG_L*i,data_shk_kai[i][j]);
}
}
for(i=0; i<config_data_count; i++) //寫入第四組鍵碼值
{
for(j=0;j<CONFIG_L;j++)
{
FLASH_ProgramByte(EEPROM_HEAD_ADDR+3+ 3*(CONFIG_L*CONFIG_W)+j+CONFIG_L*i,data_shk_guan[i][j]);
}
}
//EEPROM加上保護(hù)壕探。
FLASH_Lock(FLASH_MEMTYPE_DATA);
}
//------------------------------------------------------------------------------------------------------------
// 名稱: Read_EEPROM 冈钦。
// 功能: 讀EEPROM,若內(nèi)有有效數(shù)據(jù)則讀出 李请。
// 調(diào)用:無(wú) 瞧筛。
// 返回: 無(wú) 。
// 說(shuō)明: 無(wú)导盅。
// 形參: 無(wú) 较幌。
// 形參取值范圍: 無(wú) 。
//------------------------------------------------------------------------------------------------------------
u8 Read_EEPROM(void)
{
u8 i,j;
//EEPROM解除保護(hù)白翻。
FLASH_Unlock(FLASH_MEMTYPE_DATA); //若EEPROM的首地址即第一個(gè)字節(jié)是標(biāo)志字節(jié)乍炉,可知之前向EEPROM中寫入過(guò)數(shù)據(jù),應(yīng)讀出滤馍。?
flash_flag=FLASH_ReadByte(EEPROM_HEAD_ADDR);
if(flash_flag!=FLAG_VALIDDATA)
return 0;
soft_num=FLASH_ReadByte(EEPROM_HEAD_ADDR+1);
config_data_count=FLASH_ReadByte(EEPROM_HEAD_ADDR+2);
for(i=0; i<config_data_count; i++)
{
for(j=0; j<CONFIG_L; j++)
{
data_fun_kai[i][j] = FLASH_ReadByte(EEPROM_HEAD_ADDR+3+j+CONFIG_L*i); //讀出第一個(gè)按鍵的鍵碼組
}
}
for(i=0; i<config_data_count; i++)
{
for(j=0; j<CONFIG_L; j++)
{
data_fun_guan[i][j] = FLASH_ReadByte(EEPROM_HEAD_ADDR+3+(CONFIG_L*CONFIG_W)+j+CONFIG_L*i); //讀出第二個(gè)按鍵的鍵碼組
}
}
for(i=0; i<config_data_count; i++) //讀出第三個(gè)鍵碼的鍵碼組
{
for(j=0;j<CONFIG_L;j++)
{
data_shk_kai[i][j] = FLASH_ReadByte(EEPROM_HEAD_ADDR+3+2*(CONFIG_L*CONFIG_W)+j+CONFIG_L*i);
}
}
for(i=0; i<config_data_count; i++) //讀出第三個(gè)鍵碼的鍵碼組
{
for(j=0;j<CONFIG_L;j++)
{
data_shk_guan[i][j] = FLASH_ReadByte(EEPROM_HEAD_ADDR+3+3*(CONFIG_L*CONFIG_W)+j+CONFIG_L*i);
}
}
FLASH_Lock(FLASH_MEMTYPE_DATA);
return 1;
}
/**************************************************************************************************************************************************************************************************/
//以下是數(shù)據(jù)判斷岛琼,根據(jù)按鍵來(lái)判斷繼電器開(kāi)和關(guān)
//數(shù)據(jù)判斷,判斷遙控?cái)?shù)據(jù)是開(kāi)還是關(guān)
void data_judge(void)
{
u8 i;
for(i=0;i<config_data_count;i++)
{
if(strncmp(light_data,&(data_fun_kai[i][0]),CONFIG_L)) //判斷數(shù)據(jù)
{
FUN_ON();
if(shk_status==1)
SHK_ON();
else if(shk_status==0)
SHK_OFF();
}
else if(strncmp(light_data,&(data_fun_guan[i][0]),CONFIG_L))
{
FUN_OFF();
SHK_OFF();
}
else if(strncmp(light_data,&(data_shk_kai[i][0]),CONFIG_L))
{
SHK_ON();
shk_status=1;
}
else if(strncmp(light_data,&(data_shk_guan[i][0]),CONFIG_L))
{
SHK_OFF();
shk_status=0;
}
}
memset(light_data,0x00,3);
}