51單片機-紅外計算器
1、硬體:普中-A2開發板
使用哪些硬體資源?
1.1、LCD1602液晶顯示幕
1.2、紅外接收頭
1.3、紅外遙控器
2、軟體介紹:
2.1、共分為8個.c檔案,
2.1.1、main.c 主要負責初始化,呼叫函式進行計算、顯示
2.1.2、calculator.c 主要負責計算和字符輸入
2.1.3、delay.c 延時函式
2.1.4、lcd1602.c 液晶屏驅動函式
2.1.5、time.c 定時器初始化、中斷服務函式
2.1.6、uart.c 串口相關函式
2.1.7、Infrared.c 紅外接收函式
2.1.8、EXIT.c 外部中斷0初始化及中斷服務函式
2.2、Infrared.c和EXIT一起,用來讀取紅外遙控按鍵鍵值,紅外接收頭接在P3 ^ 2引腳上,因此一旦外部中斷0有下降沿,就進入紅外接收函式,讀取鍵值,
上代碼
1、main.c
#include <REGX52.H>
#include <intrins.h>
#include <stdio.h>
#include <string.h>
#include "time.h"
#include "lcd1602.h"
#include "delay.h"
#include "typedef.h"
#include "key.h"
#include <stdlib.h>
#include "uart.h"
#include "calculator.h"
#include "infrared.h"
uint16_t time0Cnt = 0;//本工程未用到
//主函式
int main(void)
{
LcdInit();//LCD1602初始化
Timer0Init();//定時器初始化
Timer1Init();//定時器初始化
UART_Init(9600);//串口初始化
infrared_Init();//紅外接收初始化
EA = 1;//使能所有中斷
CalculatorInit(&calculator_s);//計算器結構體初始化
setDisplayAddr(0, 0);//從第一行第一列開始顯示
printf("calculator");//上電先顯示"calculator",提示這是計算器
while(1)
{
if(infraredValue != 0)//當接收到紅外遙控器鍵值時
{
switch(getNumber(&calculator_s))//處理按鍵輸入
{
case 0://顯示運算結果
setDisplayAddr(0, 1);//顯示在第2行開頭
printf("%s", calculator_s.inputCharBuf);//LCD1602顯示計算結果
break;
case 1://顯示輸入的內容
LcdWriteCom(0x01); //清屏
setDisplayAddr(0, 0);//顯示在第一行開頭
printf("%s", calculator_s.inputCharBuf);//LCD1602顯示輸入的字串
break;
}
infraredValue = 0;
}
}
}
2、calculator.h
#ifndef __CALCULATOR_H_
#define __CALCULATOR_H_
#include <REGX52.H>
typedef struct
{
unsigned char inputCharBuf[16]; //輸入的字符陣列
unsigned int inputCharCnt; //輸入的字符個數
unsigned int offset; //遞回呼叫計算時偏移量
unsigned char errorFlag; //計算錯誤標志位 0:沒有錯誤 1:被除數等于0 2:其他
float result; //運算結果
}Calculator_S;
extern Calculator_S calculator_s; //實體化計算器需要的結構體
unsigned char keyDeal(unsigned char keyValue);
void CalculatorInit(Calculator_S *s);
unsigned char getNumber(Calculator_S *s);
float calculator(Calculator_S *s);
float calculator_core(void)reentrant;
float my_atof(const char* pbuf);
void my_cal_atof(float* result, const char *pstr, unsigned int* index);
#endif
3、calculator.c
#include "calculator.h"
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <math.h>
#include "infrared.h"
#define PRINTF 0 //為1則列印log
Calculator_S calculator_s;//實體化計算器需要的結構體
//計算器結構體全部清零
void CalculatorInit(Calculator_S *s)
{
memset(s->inputCharBuf, 0x00, sizeof(s->inputCharBuf));
s->inputCharCnt = 0;
s->result = 0;
s->offset = 0;
s->errorFlag = 0;
}
//獲取輸入的數
unsigned char getNumber(Calculator_S *s)
{
unsigned char keyValue = 0xFF;
if(infraredValue != 0)//接收到新的鍵值
{
switch(infraredValue)
{
case 0x09://前括號
s->inputCharBuf[s->inputCharCnt++] = ')';
break;
case 0x07:
s->inputCharBuf[s->inputCharCnt++] = '(';
break;
case 0x43:
if(s->inputCharCnt > 0)//洗掉一個字符
{
s->inputCharCnt--;
s->inputCharBuf[s->inputCharCnt] = 0x00;
}
break;
case 0x0d://洗掉所有字符
s->inputCharCnt = 0;
memset(s->inputCharBuf, 0x00, sizeof(s->inputCharBuf));
break;
case 0x0c:
keyValue = '1';
break;
case 0x18:
keyValue = '2';
break;
case 0x5e:
keyValue = '3';
break;
case 0x40:
keyValue = '+';
break;
case 0x08:
keyValue = '4';
break;
case 0x1c:
keyValue = '5';
break;
case 0x5a:
keyValue = '6';
break;
case 0x19:
keyValue = '-';
break;
case 0x42:
keyValue = '7';
break;
case 0x52:
keyValue = '8';
break;
case 0x4a:
keyValue = '9';
break;
case 0x45:
keyValue = '*';
break;
case 0x44:
keyValue = '.';
break;
case 0x16:
keyValue = '0';
break;
case 0x15:
keyValue = '=';
break;
case 0x47:
keyValue = '/';
break;
default:
keyValue = 0xFF;
break;
}
if(keyValue != 0xFF)
{
if(keyValue == '=' || s->inputCharCnt >= 15)//輸入的是=號
{
s->result = calculator(s);//進行計算
s->inputCharCnt = sprintf(s->inputCharBuf, "%.2f", calculator_s.result);//將計算結果放入輸入陣列中,while回圈中進行顯示
return 0;
}
else
{
/* 將輸入的字符存入字符陣列 */
s->inputCharBuf[s->inputCharCnt++] = keyValue;
return 1;
}
}
return 1;
}
return 2;//return 2 表示沒有新的按鍵
}
float calculator(Calculator_S *s)
{
s->offset = 0;//計算偏移量回到輸入陣列開頭
s->errorFlag = 0;//清除報警位
s->result = calculator_core();//呼叫計算函式進行計算
//清除狀態標志位和輸入陣列
memset(s->inputCharBuf, 0x00, sizeof(s->inputCharBuf));
s->inputCharCnt = 0;
return s->result;//回傳計算結果
}
//計算函式 reentrant表示可重入,(51單片機遞回必須算好資源)
float calculator_core(void)reentrant
{
char sign = 0;//符號變數
float number[2] = {0, 0}; //輸入的值轉換成浮點數
char numberCnt = 0;//輸入的數個數統計
sign = '+';//第一個數默認為+,因為-號會在轉換成浮點數時轉成負數
while(calculator_s.inputCharCnt > calculator_s.offset)//當輸入字符個數大于偏移量時
{
/* 遇到左括號開始遞回計算 */
if(calculator_s.inputCharBuf[calculator_s.offset] == '(')
{
#if PRINTF == 1
printf("遞回入口\r\n");
#endif
calculator_s.offset++;
calculator_s.result = calculator_core();
}
/* i == 0時可以轉換 */
if(calculator_s.offset == 0)
{
my_cal_atof(&calculator_s.result, (const char*)calculator_s.inputCharBuf, &calculator_s.offset);//字串轉float
}
/* 當本個字符是0-9數字,前一個字符不是0-9、.時,可以進行轉換 */
else if(isdigit(calculator_s.inputCharBuf[calculator_s.offset])
&& (!isdigit(calculator_s.inputCharBuf[calculator_s.offset - 1]) && calculator_s.inputCharBuf[calculator_s.offset - 1] != '.'))
{
my_cal_atof(&calculator_s.result, (const char*)calculator_s.inputCharBuf, &calculator_s.offset);//字串轉float
}
/* 非數字或者到最后一個字符了 */
if(((calculator_s.inputCharBuf[calculator_s.offset] != ' ') && (!isdigit(calculator_s.inputCharBuf[calculator_s.offset])))
|| (calculator_s.offset == calculator_s.inputCharCnt - 1))
{
switch(sign)
{
case '+':
if(numberCnt == 2)
{
number[0] += number[1];
number[1] = calculator_s.result;
}
else
{
number[numberCnt++] = calculator_s.result;
}
break;
case '-':
if(numberCnt == 2)
{
number[0] += number[1];
number[1] = -calculator_s.result;
}
else
{
number[numberCnt++] = -calculator_s.result;
}
break;
case '*':
number[numberCnt - 1] *= calculator_s.result;//與前一個數相乘
break;
case '/':
if(calculator_s.result != 0)
{
number[numberCnt - 1] /= calculator_s.result;//與前一個數相除
}
else
{
calculator_s.errorFlag = 1;//標志被除數等于0
}
break;
case '%'://取余
number[numberCnt - 1] = number[numberCnt - 1] - (int)(number[numberCnt - 1] / calculator_s.result) * calculator_s.result;
break;
default:
break;
}
#if PRINTF == 1
printf("\r\nsign:%c,%.2f, %.2f\r\n", sign, number[0], number[1]);
#endif
sign = calculator_s.inputCharBuf[calculator_s.offset];//更新當前符號
}
/* 遇到右括號回傳遞回結果 */
if(calculator_s.inputCharBuf[calculator_s.offset] == ')')
{
#if PRINTF == 1
printf("遞回出口\r\n");
#endif
calculator_s.offset++;//偏移量加1
break;
}
calculator_s.offset++;
}
#if PRINTF == 1
printf("result: %.2f\r\n", number[0] + number[1]);
#endif
return (number[0] + number[1]);
}
//本計算器專用字串轉浮點數函式,pstr是字串指標,index為字串坐標
void my_cal_atof(float* result, const char *pstr, unsigned int* index)
{
char sign = 1;//默認為正數
float point = 0.1;
*result = 0;
while (pstr[*index] < '0' || pstr[*index] > '9')
{
//去掉正負號影響
if (pstr[*index] == '-')
{
sign = 2;
}
else if(pstr[*index] == '+')
{
sign = 1;
}
(*index)++;
}
while (pstr[*index])
{
if (pstr[*index] == '.')
{
(*index)++;
while (pstr[*index] >= '0' && pstr[*index] <= '9')
{
*result += point * (pstr[*index] - '0');
point *= 0.1f;
(*index)++;
}
break;
}
else if (pstr[*index] >= '0' && pstr[*index] <= '9')
{
*result *= 10;
*result += pstr[*index] -'0';
}
else
{
break;
}
(*index)++;
}
(*index)--;
if(sign == 2)//負數
{
*result = -*result;
}
// #if PRINTF == 1
// printf("\r\nmy_cal_atof() = %.2f\r\n", *result);
// #endif
return;
}
4、delay.h
#ifndef __DELAY_H_
#define __DELAY_H_
#include "typedef.h"
#define MAIN_FOSC_DELAY 11059200UL //定義主時鐘HZ
//延時n*1ms
void delay_ms(uint16_t ms);
void delay5us(void);
void delay_us(uint16_t us);
void delay_30us(void);
void delay_40us(void);
#endif
5、delay.c
#include "delay.h"
#include <intrins.h>
void delay5us(void)
{
#if MAIN_FOSC_DELAY == 11059200UL
_nop_();
#elif MAIN_FOSC_DELAY == 12000000UL
_nop_();
#elif MAIN_FOSC_DELAY == 22118400UL
_nop_();
_nop_();
_nop_();
#endif
}
void delay_us(uint16_t us)
{
uint16_t i = us;
i = (i > 4) ? (i - 4) : i;
while(i--)
{
#if MAIN_FOSC_DELAY == 11059200UL
_nop_();
#elif MAIN_FOSC_DELAY == 12000000UL
_nop_();
#elif MAIN_FOSC_DELAY == 22118400UL
_nop_();
_nop_();
_nop_();
#endif
}
}
void delay_ms(uint16_t ms)
{
uint16_t i, j;
#if MAIN_FOSC_DELAY == 11059200UL
for(i=ms; i>0; i--)
{
for(j=114; j>0; j--)
{
;
}
}
#elif MAIN_FOSC_DELAY == 12000000UL
for(i=0; i<ms; i++)
{
for(j=0; j<123; j++)
{
;
}
}
#endif
}
//延時30微秒
void delay_30us(void)
{
#if MAIN_FOSC_DELAY == 11059200
unsigned char i;
i = 11;
while(--i);
#elif MAIN_FOSC_DELAY == 12000000
unsigned char i;
_nop_();
i = 12;
while(--i);
#endif
}
//延時40微秒
void delay_40us(void) //@11.0592MHz
{
#if MAIN_FOSC_DELAY == 11059200
unsigned char i;
_nop_();
i = 15;
while(--i);
#elif MAIN_FOSC_DELAY == 12000000
unsigned char i;
_nop_();
i = 17;
while(--i);
#endif
}
6、typedef.h
#ifndef __TYPEDEF_H_
#define __TYPEDEF_H_
//#define uint16_t unsigned int
#define __WEAK __attribute__((weak))
typedef unsigned long uint32_t;
typedef unsigned int uint16_t;
typedef unsigned char uint8_t;
#endif
7、lcd1602.h
#ifndef __LCD1602_H_
#define __LCD1602_H_
#define QUICK 1 //有此宏定義時,為快速模式,否則為慢速模式
/**********************************
包含頭檔案
**********************************/
#include <REGX52.H>
#include "typedef.h"
/**********************************
PIN口定義
**********************************/
#define LCD1602_DATAPINS P0
sbit LCD1602_RS=P2^6;
sbit LCD1602_RW=P2^5;
sbit LCD1602_E=P2^7;
extern unsigned char code userCodeBuf[];//用戶自定義的7個字的地址陣列
/**********************************
函式宣告
**********************************/
/*在51單片機12MHZ時鐘下的延時函式*/
void Lcd1602_Delay1ms(uint16_t c); //誤差 0us
/*LCD1602寫入8位命令子函式*/
void LcdWriteCom(uint8_t com);
/*LCD1602寫入8位資料子函式*/
void LcdWriteData(uint8_t dat) ;
/*LCD1602初始化子程式*/
void LcdInit();
void displayString(uint8_t* buf, uint16_t N, uint8_t Lin);
void setDisplayAddr(unsigned char x, unsigned char y);
#endif
8、lcd1602.c
#include "lcd1602.h"
#include "delay.h"
#include <stdio.h>
#ifdef UART //定義才呼叫下方的檔案頭
#include "uart.h"
#endif
/* 字符獲取方式:
點陣格式:陰碼
取模走向:順向
取模方式:逐行式
輸出數制:十六進制
用8*8點陣的后5列
*/
unsigned char code table[]= {
0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,//一
0x00,0x00,0x0E,0x00,0x1F,0x00,0x00,0x00,//二
0x00,0x1F,0x00,0x0E,0x00,0x1F,0x00,0x00,//三
0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,//年
0x0f,0x09,0x0f,0x09,0x0f,0x09,0x0b,0x11,//月
0x0F,0x09,0x09,0x0F,0x09,0x09,0x0F,0x00,//日
0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,//冒號
0x18,0x18,0x07,0x08,0x08,0x08,0x07,0x00//℃
};
code unsigned char userCodeBuf[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}; //自定義字符資料地址
//重寫putchar函式
char putchar(char c)
{
if(c >= 0x20 && c <= 0x7E)
{
LcdWriteData(c); //顯示一個字符
}
#ifdef UART
sendByte(c);
#endif
return c;
}
void setDisplayAddr(unsigned char x, unsigned char y)
{
LcdWriteCom(0x80 + x + 0x40 * y); //設定資料指標起點,從LCD頭部開始顯示
}
/*******************************************************************************
* 函 數 名 : displayString
* 函式功能 : LCD1602顯示一串字串 ,buf 為要顯示的陣列,N為要顯示的長度,Lin為要顯示在哪行
* 輸 入 : 無
* 輸 出 : 無
*******************************************************************************/
void displayString(uint8_t* buf, uint16_t N, uint8_t Lin)
{
int i;
N = (N > 16) ? 16 : N;//防止出現大于16的情況
if(Lin == 0)
{
LcdWriteCom(0x80); //設定資料指標起點,從LCD頭部開始顯示
}
else
{
LcdWriteCom(0x80 + 0x40); //第二行顯示
}
for(i = 0; i < N; i++)
{
LcdWriteData(buf[i]); //顯示一個字符
}
}
//判斷忙指令
void Busy(void)
{
LCD1602_DATAPINS = 0xff;
LCD1602_RS = 0;
LCD1602_RW = 1;
while(LCD1602_DATAPINS & 0x80)
{
LCD1602_E = 0;
LCD1602_E = 1;
}
LCD1602_E = 0;
}
/*******************************************************************************
* 函 數 名 : LcdWriteCom
* 函式功能 : 向LCD寫入一個位元組的命令
* 輸 入 : com
* 輸 出 : 無
*******************************************************************************/
void LcdWriteCom(uint8_t com) //寫入命令
{
Busy();
LCD1602_RS = 0; //選擇發送命令
LCD1602_RW = 0; //選擇寫入
LCD1602_DATAPINS = com; //放入命令
delay_ms(1); //等待資料穩定
LCD1602_E = 1; //寫入時序
#ifdef QUICK
delay_ms(1); //保持時間
#else
delay_ms(5); //保持時間
#endif
LCD1602_E = 0;
}
/*******************************************************************************
* 函 數 名 : LcdWriteData
* 函式功能 : 向LCD寫入一個位元組的資料
* 輸 入 : dat
* 輸 出 : 無
*******************************************************************************/
void LcdWriteData(uint8_t dat) //寫入資料
{
Busy();
LCD1602_RS = 1; //選擇輸入資料
LCD1602_RW = 0; //選擇寫入
LCD1602_DATAPINS = dat; //寫入資料
delay_ms(1);
LCD1602_E = 1; //寫入時序
#ifdef QUICK
delay_ms(1); //保持時間
#else
delay_ms(5); //保持時間
#endif
LCD1602_E = 0;
}
/*******************************************************************************
* 函 數 名 : LcdInit()
* 函式功能 : 初始化LCD屏
* 輸 入 : 無
* 輸 出 : 無
*******************************************************************************/
void LcdInit() //LCD初始化子程式
{
unsigned char i = 0;
//等待LCD1602初始化
delay5us();
delay_us(5);
delay_30us();
delay_40us();
LcdWriteCom(0x38); //開顯示
LcdWriteCom(0x0c); //開顯示不顯示游標
LcdWriteCom(0x06); //寫一個指標加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //設定資料指標起點
setDisplayAddr(0, 0);
displayString("lcd1602 Init", 12, 0);
/* 開始寫入你要顯示的自定義字符、漢字代碼 */
LcdWriteCom(0x40);
for(i=0; i<64; i++)
{
LcdWriteData(table[i]);
}
displayString(" ", 12, 0);
}
9、time.h
#ifndef __TIME_H_
#define __TIME_H_
#include <REGX52.H>
#include "typedef.h"
#define T1MS_0 (65536-MAIN_FOSC_DELAY/12/1000) //1ms timer calculation method in 12T mode
#define T1MS_1 (65536-MAIN_FOSC_DELAY/12/1000) //1ms timer calculation method in 12T mode
//定時器0
void Timer0Init(void); //定時器初始化為1ms一次
//定時器1
void Timer1Init(void); //定時器初始化為1ms一次
#endif
10、time.c
#include "time.h"
#include "delay.h"
#ifdef ADC0809 //定義才呼叫下方的檔案頭
#include "ADC0809.h"
#endif
#ifdef UART //定義才呼叫下方的檔案頭
#include "uart.h"
#endif
extern uint16_t time0Cnt;
//定時器0中斷
void Timer0Init(void) //定時器初始化為1ms一次
{
TMOD |= 0X01; //選擇為定時器0模式,作業方式1,僅用TR0打開啟動,
TL0 = T1MS_0;//給定時器賦初值,定時1ms ,計算方式(65536 -(12/12*1000))%256
TH0 = T1MS_0 >> 8;//給定時器賦初值,定時1ms ,計算方式(65536 -(12/12*1000))/256
ET0 = 1; //打開定時器0中斷允許
TR0 = 1; //打開定時器
}
//定時器1中斷
void Timer1Init(void) //定時器初始化為1ms一次
{
TMOD |= 0x10; //set timer1 as mode1 (16-bit)
TL1 = T1MS_1; //initial timer1 low byte
TH1 = T1MS_1 >> 8; //initial timer1 high byte
TR1 = 0; //timer1 start running
ET1 = 1; //enable timer1 interrupt
}
void time0_isr() interrupt 1 using 0
{
TL0 = T1MS_0;//手動重裝載
TH0 = T1MS_0 >> 8;//手動重裝載
#ifdef ADC0809
CLK = !CLK;//ADC0809的時鐘信號
#endif
#ifdef UART
if(timeout < RECEIVE_TIMEOUT)//當小于接收超時時間時
{
if(++timeout == RECEIVE_TIMEOUT)
{
receiveFinshFlag = 1;//串口1幀資料接收完畢
}
}
#endif
time0Cnt++;
}
/* Timer0 interrupt routine */
void time1_isr() interrupt 3 using 1
{
TL1 = T1MS_1; //reload timer1 low byte
TH1 = T1MS_1 >> 8; //reload timer1 high byte
}
11、uart.h
#ifndef __UART_H_
#define __UART_H_
#include <REGX52.H>
#define RECEIVE_TIMEOUT 5 //接收超時時間設為5ms
#define RECEIVE_LENGTH 5 //接收長度為5位元組
extern volatile unsigned char UART_Buf[RECEIVE_LENGTH];//串口接收陣列
extern volatile unsigned char receiveCnt;//串口接收的資料長度
extern volatile unsigned int timeout;//接收超時
extern volatile bit receiveFinshFlag;//接收完畢標志位
void UART_Init(unsigned int baud);
void sendString(unsigned char* s, int length);
void sendByte(unsigned char b);
#endif
12、uart.c
#include "uart.h"
#include "delay.h"
volatile unsigned char UART_Buf[RECEIVE_LENGTH];//串口接收陣列
volatile unsigned char receiveCnt = 0;//串口接收的資料長度
volatile unsigned int timeout = 0xFF;
volatile bit receiveFinshFlag = 0;//接收完畢標志位
//串口1中斷服務函式
void UART_isr(void) interrupt 4 using 1
{
UART_Buf[receiveCnt++] = SBUF;
timeout = 0;
receiveCnt = (receiveCnt >= RECEIVE_LENGTH) ? 0 : receiveCnt;//防止陣列越界
RI = 0;//清除接收中斷標志位
}
//串口初始化 0:2400 1:4800 2:9600
void UART_Init(unsigned int baud)
{
TMOD &= 0x0F;
TMOD |= 0x20;
TH1 = -(MAIN_FOSC_DELAY/12/32/baud); //Set auto-reload vaule
TL1 = -(MAIN_FOSC_DELAY/12/32/baud); //Set auto-reload vaule
SCON = 0x50;
ET1 = 0;
TR1 = 1;
ES = 1;
sendString("UART is OK!\r\n", 13);
}
/*******發送一個位元組到串口*************************************************************/
void sendByte(unsigned char b)
{
ES = 0;
SBUF = b;
while(!TI);
TI = 0;
ES = 1;
}
/*******發送一個字串到串口*************************************************************/
void sendString(unsigned char* s, int length)
{
int i;
for(i = 0; i < length; i++)
{
sendByte(s[i]);
}
}
13、Infrared.h
#ifndef __INFRARED_H_
#define __INFRARED_H_
#include <REGX52.H>
#include "typedef.h"
sbit infrared_in = P3 ^ 2;//紅外接收頭引腳
extern unsigned char infraredValue;//紅外接收鍵值
void infrared_Init(void);
void readInfrared(unsigned char* dat);
#endif
14、Infrared.c
#include "infrared.h"
#include "delay.h"
#include "EXIT.h"
#include <intrins.h>
unsigned char infraredValue;//紅外接收鍵值
//紅外通訊初始化
void infrared_Init(void)
{
EXIT0_Init();//外部中斷0初始化
EA = 1;
infrared_in = 1;
}
void readInfrared(unsigned char* dat)
{
unsigned char i,j;//回圈控制變數
unsigned char Time;//高電平時間計算
unsigned int errorCnt;//等待計時
unsigned char readBuf[2];//臨時存放陣列
Time = 0;
delay_ms(7); //7ms
if(!infrared_in) //確認是否真的接收到正確的信號
{
errorCnt = 1000; //1000*10us=10ms,超過說明接收到錯誤的信號
/*當兩個條件都為真是回圈,如果有一個條件為假的時候跳出回圈,免得程式出錯的時
侯,程式死在這里*/
while((infrared_in == 0)&&( errorCnt > 0)) //等待前面9ms的低電平過去
{
delay_us(1);
errorCnt--;
}
if(infrared_in == 1) //如果正確等到9ms低電平
{
errorCnt = 500;
while((infrared_in == 1) && (errorCnt > 0)) //等待4.5ms的起始高電平過去
{
delay_us(1);
errorCnt--;
}
for(i=0; i<4; i++) //共有4組資料
{
for(j=0; j<8; j++) //接收一位元組資料
{
errorCnt = 60;
while((infrared_in == 0)&&(errorCnt > 0))//等待信號前面的560us低電平過去
{
delay_us(10);
errorCnt--;
}
errorCnt = 500;
while((infrared_in == 1) && (errorCnt > 0)) //計算高電平的時間長度,
{
delay_us(10); //0.1ms
Time++;
errorCnt--;
if(Time > 30)
{
return;
}
}
readBuf[i%2] >>= 1; //i表示第幾組資料
if(Time >= 8) //如果高電平出現大于565us,那么是1
{
readBuf[i%2] |= 0x80;
}
Time = 0; //用完時間要重新賦值
}
}
}
//校驗失敗,則讓值等于0
if(readBuf[0] != ~readBuf[1])
{
*dat = 0;
}
else
{
*dat = readBuf[0];//校驗成功,得到鍵值
}
}
}
15、EXIT.h
#ifndef __EXIT_H_
#define __EXIT_H_
#include "typedef.h"
void EXIT0_Init(void);
void EXIT1_Init(void);
#endif
16、EXIT.c
#include "EXIT.h"
#include "infrared.h"
#include <REGX52.H>
#ifdef EXIT_0
void EXIT0_Init(void)
{
IT0=1; //INT0負跳變觸發
EX0 = 1; //開外部INTO中斷
}
//外部中斷0中斷服務函式
void exint0() interrupt 0 //(location at 0003H)
{
#ifdef INFRARED //若在keil編譯指令中定義了這個宏,且為1,這呼叫下方讀取紅外信號的函式
readInfrared(&infraredValue);
#endif
}
#endif
#ifdef EXIT_1
void EXIT1_Init(void)
{
IT1=1; //INT1負跳變觸發
EX1 = 1; //開外部INTO中斷
}
//外部中斷1中斷服務函式
void exint1() interrupt 2 //(location at 0013H)
{
}
#endif
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/293432.html
標籤:其他
