|
我做了個 2.4G 遙控器 下面有附圖 有源碼 有感興趣的 可以學學 了 。當時做的時候也學習了很長時間 。由于自己感興趣 ,就學下去了 收益匪淺啊。很適合初學者看看了 。本程序 做個小車 小船的 灼灼有余了 。這是發射程序 #include <reg51.h>#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define u8 unsigned char
#define u16 unsigned int
//STC12 系列新增寄存器
sfr IPH=0xb7;
sfr P4=0xc0;
sfr P4SW=0xbb;
sfr P1ASF=0x9d;
sfr P4M0=0xb4;
sfr P3M0=0xb2;
sfr P3M1=0xb1;
sfr P2M0=0x96;
sfr P0M0=0x94;
sfr ADC_CONTR=0xbc;
sfr ADC_RES=0xbd;
sfr ADC_RESL=0xbe;
sfr BRT=0x9c;
sfr AUXR=0x8e;
sfr WAKE_CLKO=0x8f;
sfr IAP_DATA=0xc2;
sfr IAP_ADDRH=0xc3;
sfr IAP_ADDRL=0xc4;
sfr IAP_CMD=0xc5;
sfr IAP_TRIG=0xc6;
sfr IAP_CONTR=0xc7;
sfr CCON = 0xD8; //PCA control register
sbit CCF0 = CCON^0; //PCA module-0 interrupt flag
sbit CCF1 = CCON^1; //PCA module-1 interrupt flag
sbit CR = CCON^6; //PCA timer run control bit
sfr CMOD = 0xD9; //PCA mode register
sfr CL = 0xE9; //PCA base timer LOW
sfr CH = 0xF9; //PCA base timer HIGH
sfr CCAPM0 = 0xDA; //PCA module-0 mode register
sfr CCAP0L = 0xEA; //PCA module-0 capture register LOW
sfr CCAP0H = 0xFA; //PCA module-0 capture register HIGH
sfr CCAPM1 = 0xDB; //PCA module-1 mode registers
sfr CCAP1L = 0xEB; //PCA module-1 capture register LOW
sfr CCAP1H = 0xFB; //PCA module-1 capture register HIGH
/*************************************************/
/* STC15W404AS寄存器補充
sfr AUXR1 = 0XA2;
sfr AUXR = 0X8E;
sfr TH2 = 0XD6;
sfr TL2 = 0XD7;
sfr P4 = 0xc0;
sfr P5 = 0xc8;
sfr P3M0=0xB2;
sfr SPSTAT = 0xCD; //
sfr SPCTL = 0xCE; //
sfr SPDAT = 0xCF; */
//定時器2
//sfr T2H=0xd6;
//sfr T2L=0xd7;
//sfr IE2=0xaf;
//ADC
//sfr ADC_CONTR = 0xBC; //帶AD系列
//sfr ADC_RES = 0xBD; //帶AD系列
//sfr ADC_RESL = 0xBE; //帶AD系列
//sfr P1ASF = 0x9D;
sfr PCON2 = 0x97;
#define ADC_POWER 0x80//ADC電源控制位
#define ADC_FLAG 0x10//ADC完成標志
#define ADC_START 0x08//ADC起始控制位
#define ADC_SPEEDLL 0x00//540個時鐘轉換一次
#define ADC_SPEEDL 0x20//360時鐘
#define ADC_SPEEDH 0x40//180時鐘
#define ADC_SPEEDHH 0x60//90時鐘
unsigned char recv_buf[6]={0,0,0,0,1,1};//NRF24模塊可以一次發射32個字節,這里只用6個,代表6個通道。
sbit NRF_CE = P0^1;
sbit NRF_CSN = P0^0;
sbit NRF_MISO = P0^5;
sbit NRF_MOSI = P0^2;
sbit NRF_SCK = P0^3;
sbit NRF_IRQ = P0^4;
/*sbit NRF_IRQ = P5^5;
sbit NRF_MISO = P1^4;
sbit NRF_MOSI = P1^3;
sbit NRF_SCK = P1^5;
sbit NRF_CSN = P1^2;
sbit NRF_CE = P5^4; */
sbit SW1=P3^7;//開關通道1
sbit SW2=P3^6;//開關通道2
sbit SW_Mix1=P3^5;//混控開關1
//sbit Beep=P3^4;//蜂鳴器
//sbit LED_Battery=P3^3;//1s電池低壓報警燈
sbit LED_NRF=P3^2;//NRF模塊信號不好報警燈
u8 TxAllCount=0;//發射總次數
u8 TxOKCount=0;//發射成功次數
u8 Time10Ms=0;//蜂鳴器鳴叫時間
/*
有些搖桿,阻值5K的,搖到最上方,還有大概1K的阻值,阻值并不是0的樣子。
有些搖桿,搖到最上邊阻值就是0了。
這樣搖不到底的搖桿,我不做轉換了,電調有行程調節的。
接舵機倒無所謂,大不了轉不了45度,我轉個30°也湊合了。
*/
u8 pianyi=25;//搖桿上限偏移范圍上限值,默認25,你也可以修改。
/********** 你可以從這里復制NRF24L01的全部代碼了 ***********/
/********** NRF24L01寄存器操作命令 ***********/
#define READ_REG 0x00 //讀配置寄存器,低5位為寄存器地址
#define WRITE_REG 0x20 //寫配置寄存器,低5位為寄存器地址
#define RD_RX_PLOAD 0x61 //讀RX有效數據,1~32字節
#define WR_TX_PLOAD 0xA0 //寫TX有效數據,1~32字節
#define FLUSH_TX 0xE1 //清除TX FIFO寄存器.發射模式下用
#define FLUSH_RX 0xE2 //清除RX FIFO寄存器.接收模式下用
#define REUSE_TX_PL 0xE3 //重新使用上一包數據,CE為高,數據包被不斷發送.
#define NRF_NOP 0xFF //空操作,可以用來讀狀態寄存器
/********** NRF24L01寄存器地址 *************/
#define CONFIG 0x00 //配置寄存器地址
#define EN_AA 0x01 //使能自動應答功能
#define EN_RXADDR 0x02 //接收地址允許
#define SETUP_AW 0x03 //設置地址寬度(所有數據通道)
#define SETUP_RETR 0x04 //建立自動重發
#define RF_CH 0x05 //RF通道
#define RF_SETUP 0x06 //RF寄存器
#define STATUS 0x07 //狀態寄存器
#define OBSERVE_TX 0x08 // 發送檢測寄存器
#define CD 0x09 // 載波檢測寄存器
#define RX_ADDR_P0 0x0A // 數據通道0接收地址
#define RX_ADDR_P1 0x0B // 數據通道1接收地址
#define RX_ADDR_P2 0x0C // 數據通道2接收地址
#define RX_ADDR_P3 0x0D // 數據通道3接收地址
#define RX_ADDR_P4 0x0E // 數據通道4接收地址
#define RX_ADDR_P5 0x0F // 數據通道5接收地址
#define TX_ADDR 0x10 // 發送地址寄存器
#define RX_PW_P0 0x11 // 接收數據通道0有效數據寬度(1~32字節)
#define RX_PW_P1 0x12 // 接收數據通道1有效數據寬度(1~32字節)
#define RX_PW_P2 0x13 // 接收數據通道2有效數據寬度(1~32字節)
#define RX_PW_P3 0x14 // 接收數據通道3有效數據寬度(1~32字節)
#define RX_PW_P4 0x15 // 接收數據通道4有效數據寬度(1~32字節)
#define RX_PW_P5 0x16 // 接收數據通道5有效數據寬度(1~32字節)
#define FIFO_STATUS 0x17 // FIFO狀態寄存器
/*————————————————————————————————————————————————————————————————————*/
/****** STATUS寄存器bit位定義 *******/
#define MAX_TX 0x10 //達到最大發送次數中斷
#define TX_OK 0x20 //TX發送完成中斷
#define RX_OK 0x40 //接收到數據中斷
/*——————————————————————————————————————————————————*/
/********* 24L01發送接收數據寬度定義 ***********/
#define TX_ADR_WIDTH 5 //5字節地址寬度
#define RX_ADR_WIDTH 5 //5字節地址寬度
#define TX_PLOAD_WIDTH 6 //32字節有效數據寬度
#define RX_PLOAD_WIDTH 6 //32字節有效數據寬度
uchar xdata TX_ADDRESS[TX_ADR_WIDTH]={0x68,0x86,0x66,0x88,0x28};
uchar xdata RX_ADDRESS[RX_ADR_WIDTH]={0x68,0x86,0x66,0x88,0x28};
void Delay1ms() //@12.000MHz 軟件延時1ms
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
void delay_ms(unsigned char i) //延時n毫秒 0~255ms
{
while(--i)
{
Delay1ms();
}
}
void DelayMs(unsigned int i) //延時N毫秒,0~65535ms
{
while(--i)
{
Delay1ms();
}
}
/**********************/
/* 初始化硬件SPI口 */
/*
void SPI_Init(void) //如果用模擬SPI,這個就不要調用了,它是開啟硬件SPI
{
SPSTAT |= 0xC0; //SPI狀態寄存器全部清0 SPIF和WCOL清0
SPCTL = 0xD0; //0xD0=11010000 ,表示SPI開啟,主機模式,SPI頻率為主頻四分之一
} */
/**********************/
/* SPI數據收發函數 硬件SPI */
/*
uchar SPI_RW(uchar tr_data)
{
uchar i=0;
SPSTAT |= 0xc0; //SPI狀態寄存器全部清0 SPIF和WCOL清0
SPDAT=tr_data; //將數據放到SPI數據寄存器中
while(((SPSTAT&0x80)!=0x80)&&(i<20)) //SPSTAT&0x80 SPI數據傳輸完成標志 如果沒完成傳輸,就延時1ms
{
i++;
delay_ms(1); //20ms內沒完成,則跳出
}
return SPDAT; //返回傳輸的數據值
} */
// 下面是“模擬SPI” 如果不用硬件SPI,可以用模擬SPI
uchar SPI_RW(uchar byte)
{
uchar bit_ctr;
for(bit_ctr=0;bit_ctr<8;bit_ctr++) // 輸出8位
{
NRF_MOSI=(byte&0x80); // MSB TO MOSI
byte=(byte<<1); // shift next bit to MSB
NRF_SCK=1;
byte|=NRF_MISO; // capture current MISO bit
NRF_SCK=0;
}
return byte;
}
/*********************************************/
/* 函數功能:給24L01的寄存器寫值(一個字節) */
/* 入口參數:reg 要寫的寄存器地址 */
/* value 給寄存器寫的值 */
/* 出口參數:status 狀態值 */
/*********************************************/
uchar NRF24L01_Write_Reg(uchar reg,uchar value)
{
uchar status;
NRF_CSN=0; //CSN=0;
status = SPI_RW(reg);//發送寄存器地址,并讀取狀態值
SPI_RW(value);
NRF_CSN=1; //CSN=1;
return status;
}
/*************************************************/
/* 函數功能:讀24L01的寄存器值 (一個字節) */
/* 入口參數:reg 要讀的寄存器地址 */
/* 出口參數:value 讀出寄存器的值 */
/*************************************************/
uchar NRF24L01_Read_Reg(uchar reg)
{
uchar value;
NRF_CSN=0; //CSN=0;
SPI_RW(reg);//發送寄存器值(位置),并讀取狀態值
value = SPI_RW(NRF_NOP);
NRF_CSN=1; //CSN=1;
return value;
}
/*********************************************/
/* 函數功能:讀24L01的寄存器值(多個字節) */
/* 入口參數:reg 寄存器地址 */
/* *pBuf 讀出寄存器值的存放數組 */
/* len 數組字節長度 */
/* 出口參數:status 狀態值 */
/*********************************************/
uchar NRF24L01_Read_Buf(uchar reg,uchar *pBuf,uchar len)
{
uchar status,u8_ctr;
NRF_CSN=0; //CSN=0
status=SPI_RW(reg);//發送寄存器地址,并讀取狀態值
for(u8_ctr=0;u8_ctr<len;u8_ctr++)
pBuf[u8_ctr]=SPI_RW(0XFF);//讀出數據
NRF_CSN=1; //CSN=1
return status; //返回讀到的狀態值
}
/**********************************************/
/* 函數功能:給24L01的寄存器寫值(多個字節) */
/* 入口參數:reg 要寫的寄存器地址 */
/* *pBuf 值的存放數組 */
/* len 數組字節長度 */
/**********************************************/
uchar NRF24L01_Write_Buf(uchar reg, uchar *pBuf, uchar len)
{
uchar status,u8_ctr;
NRF_CSN=0;
status = SPI_RW(reg);//發送寄存器值(位置),并讀取狀態值
for(u8_ctr=0; u8_ctr<len; u8_ctr++)
SPI_RW(*pBuf++); //寫入數據
NRF_CSN=1;
return status; //返回讀到的狀態值
}
//為避免編譯器函數重入錯誤,所以又改名復制的函數,和上面的函數一個樣
uchar NRF24L01_Write_BufData(uchar reg, uchar *pBuf, uchar len)
{
uchar status,u8_ctr;
NRF_CSN=0;
status = SPI_RW(reg);//發送寄存器值(位置),并讀取狀態值
for(u8_ctr=0; u8_ctr<len; u8_ctr++)
SPI_RW(*pBuf++); //寫入數據
NRF_CSN=1;
return status; //返回讀到的狀態值
}
/*********************************************/
/* 函數功能:24L01接收數據 */
/* 入口參數:rxbuf 接收數據數組 */
/* 返回值: 0 成功收到數據 */
/* 1 沒有收到數據 */
/*********************************************/
uchar NRF24L01_RxPacket(uchar *rxbuf)
{
uchar state;
state=NRF24L01_Read_Reg(STATUS); //讀取狀態寄存器的值
NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中斷標志
if(state&RX_OK)//接收到數據
{
NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//讀取數據
NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
return 0;
}
return 1;//沒收到任何數據
}
/**********************************************/
/* 函數功能:設置24L01為發送模式 */
/* 入口參數:txbuf 發送數據數組 */
/* 返回值; 0x10 達到最大重發次數,發送失敗*/
/* 0x20 成功發送完成 */
/* 0xff 發送失敗 */
/**********************************************/
uchar NRF24L01_TxPacket(uchar *txbuf)
{
uchar state;
// uchar i;
NRF_CE=0;//CE拉低,使能24L01配置
NRF24L01_Write_BufData(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//寫數據到TX BUF 32個字節
NRF_CE=1;//CE置高,使能發送
while(NRF_IRQ==1);//等待發送完成
state=NRF24L01_Read_Reg(STATUS); //讀取狀態寄存器的值
NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中斷標志
if(state&MAX_TX)//達到最大重發次數
{
NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器
return MAX_TX;
}
if(state&TX_OK)//發送完成
{
return TX_OK;
}
return 0xff;//發送失敗
}
/********************************************/
/* 函數功能:檢測24L01是否存在 */
/* 返回值; 0 存在 */
/* 1 不存在 */
/********************************************/
//檢測原理就是存入NRF模塊一段數據,然后再讀出來比較一下是否一致
uchar NRF24L01_Check(void)
{
uchar check_in_buf[5]={0x11,0x22,0x33,0x44,0x55};
uchar check_out_buf[5]={0x00};
NRF_CE=0;
NRF24L01_Write_Buf(WRITE_REG+TX_ADDR, check_in_buf, 5);
NRF24L01_Read_Buf(READ_REG+TX_ADDR, check_out_buf, 5);
if((check_out_buf[0] == 0x11)&&\
(check_out_buf[1] == 0x22)&&\
(check_out_buf[2] == 0x33)&&\
(check_out_buf[3] == 0x44)&&\
(check_out_buf[4] == 0x55))return 0;
else return 1;
}
void NRF24L01_SET_TX_Mode(void)
{
NRF_CE=0;
NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0e); // 配置為無線發送模式
NRF_CE=1;
}
void NRF24L01_SET_RX_Mode(void)
{
NRF_CE=0;
NRF24L01_Write_Reg(WRITE_REG+CONFIG, 0x0f); // 配置為無線接收模式
NRF_CE=1;
}
void NRF24L01_RT_Init(void) //NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0e); 發射時0x0e,記得修改
{
NRF_CE=0; //進行配置,要首先禁止模塊功能
NRF24L01_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//選擇通道0的有效數據寬度
NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
NRF24L01_Write_Buf(WRITE_REG+TX_ADDR,(uchar*)TX_ADDRESS,TX_ADR_WIDTH);//寫TX節點地址
NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(uchar*)RX_ADDRESS,RX_ADR_WIDTH); //設置TX節點地址,主要為了使能ACK
NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x01); //使能通道0的自動應答
NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址
NRF24L01_Write_Reg(WRITE_REG+SETUP_RETR,0x1a);//設置自動重發間隔時間:500us + 86us;最大自動重發次數:10次
NRF24L01_Write_Reg(WRITE_REG+RF_CH,40); //設置RF通道為125
NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x27); //7db增益,250kbps
NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0e); //配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啟所有中斷
NRF_CE=1; //CE置1,恢復功能 //0x0e發射 0x0f接收
} //記得發送程序和接收程序的配置,要改0e和0f的數值,要不就要單獨要用一次發射或者接收設置。
/********** NRF24L01的全部代碼復制完成了 ***********/
/*void BEEP(u8 i) //蜂鳴器叫兩聲
{
Beep=1;
DelayMs(i);
Beep=0;
DelayMs(i);
Beep=1;
DelayMs(i);
Beep=0;
}
/*void TimeBEEP() //用定時器2讓蜂鳴器間隔鳴叫
{
AUXR=0x10;//打開定時器2
}
*/
void InitADC(void) //ADC初始化
{
P1ASF=0xc3;//打開P1.0,P1.1,P1.6,P1.7的ADC轉換功能 因為這里就用了4個腳 0xc3=11000011 對應P1.7~P1.0 8個腳
ADC_RES=0;//ADC的值清0
ADC_CONTR=ADC_POWER | ADC_SPEEDLL;//打開ADC的電源 540個時鐘轉換一次
delay_ms(2);//延遲2ms等待穩定
}
u16 Get_ADC10bitResult(u8 channel) //獲取10位精度的ADC值
{
u16 adc;
u8 i;
if(channel > 7) return 1024; //錯誤,返回1024, ADC通道號0~7,不能超過7
ADC_RES = 0; //高位ADC清零
ADC_RESL = 0;//低位ADC清零
ADC_CONTR = (ADC_CONTR & 0xe0) | ADC_START | channel; //打開指定通道的ADC轉換
_nop_();
_nop_();
_nop_();
_nop_(); //對ADC_CONTR操作后要4T之后才能訪問
for(i=0; i<250; i++) //250us內要轉換完成,否則超時跳出
{
if(ADC_CONTR & ADC_FLAG) //轉換完成后,ADC_FLAG=1,所以這里判斷ADC_FLAG是不是為1
{
ADC_CONTR &= ~ADC_FLAG; //ADC_FLAG手工清0
if(PCON2 & (1<<5))//根據ADRJ判斷ADC轉換值放在哪里 如果是1
{
adc = (u16)(ADC_RES & 3); //10位AD結果的高2位放ADC_RES的低2位,低8位在ADC_RESL。
adc = (adc << 8) | ADC_RESL; //3=二進制的11 &3是獲取低2位的值 <<8 | ADC_RESL 是獲取低8位的值
}
else //10位AD結果的高8位放ADC_RES,低2位在ADC_RESL的低2位。
{
adc = (u16)ADC_RES;
adc = (adc << 2) | (ADC_RESL & 3);
}
return adc;
}
}
return 1024; //如果超時,返回1024,調用的程序判斷
}
/*******************************************
注意:下載時,下載界面"硬件選項"中下面的項要固定如下設置:
不勾選 允許低壓復位(禁止低壓中斷)
低壓檢測電壓 3.70V
選擇CPU-CORE最高電壓 2.74V
******************************************
void CheckLiBattery() //檢測電池電壓
{
if(PCON & (1<<5))//檢測到低電壓
{
LED_Battery=1; //低壓報警LED燈亮
TimeBEEP(); //蜂鳴器叫
}
else
{
LED_Battery=0; //關燈
}
PCON &= ~(1<<5);//低壓檢測標志清0 ,為下次檢測做準備
}
*/
//u8 GetNewYM(u8 ym,u8 minym,u8 maxym)//根據最大和最小油門,轉換到0~255范圍的新油門值
//{
// //最小油門 中點值固定128 最大油門 轉為成0 128 255
//// return ym;
// if(ym<128)return (ym-minym)*128/(128-minym); //等比例縮小
// else
// if(ym>128)return 127+(ym-128)*128/(maxym-128);//等比例放大
// else
// return 128;
//}
void GetNRFTxDate()
{
u8 fy,sj;
recv_buf[0]=Get_ADC10bitResult(0)>>2;//P1.0 一通副翼 >>2的意思就是除以4 10位精度再轉8位的
recv_buf[1]=Get_ADC10bitResult(1)>>2;//P1.1 二通升降
recv_buf[2]=Get_ADC10bitResult(6)>>2;//P1.6 三通油門
recv_buf[3]=Get_ADC10bitResult(7)>>2;//P1.7 四通方向
recv_buf[4]=SW1;//P3.7 五通 開關通道
recv_buf[5]=SW2;//P3.6 六通 開關通道
fy=recv_buf[0];
sj=recv_buf[1];
if (SW_Mix1==0)//當混控開關1打開
{
//這里混控可以根據混控開關,做成副翼和升降混控 方向和油門插速混控等模式
//我只設定了一個混控開關,郁悶了。混控形式太多,單片機引腳不夠用了……你們自己改吧
/* 混控一
比如我改個副翼和升降的混控 也就是一通道和二通道進行混控
升降的時候,兩個舵機同一個方向
副翼的時候,兩個舵機方向相反
*/
/* 混控二
雙電機的飛機,方向用電機差速控制,也就是副翼和油門的混控,一通道和三通道混控
加減油門,兩個舵機同一方向
副翼的時候,兩個舵機方向相反
*/
//下面我只寫混控一,混控x之類的,大家可以模仿著寫。其實我也沒寫過。我連架紙飛機都沒。
//先判斷是搖桿是升降還是副翼 加上75作為誤差值
if (fy-pianyi>=128||fy+pianyi<=128)//副翼搖桿移動
{
recv_buf[1]=255-fy; //升降通道要反相
};
//先判斷是搖桿是升降還是副翼
if (sj-pianyi>=128||sj+pianyi<=128)//升降搖桿移動
{
recv_buf[0]=sj; //升降要同相
};
}
}
void Timer0Init(void) //19毫秒@12.000MHz
{
AUXR &= 0x7F; //定時器時鐘12T模式
TMOD &= 0xF0; //設置定時器模式
TL0 = 0xC8; //設置定時初值
TH0 = 0xB5; //設置定時初值
TF0 = 0; //清除TF0標志
TR0 = 1; //定時器0開始計時
ET0 = 1; //開通定時器0中斷
EA = 1; //開啟全部中斷
}
/*void Timer2Init(void) //10毫秒@12.000MHz
{
AUXR &= 0xFB; //定時器時鐘12T模式
T2L = 0xF0; //設置定時初值
T2H = 0xD8; //設置定時初值
IE2 |=0x04; //ET2=1 //允許定時器2的中斷
EA = 1; //開啟全部中斷
AUXR=0;//禁止定時器2運行
//AUXR |= 0x10; //定時器2開始計時
}
*/
void main(void)
{
delay_ms(100); // 延時待系統穩定
SW1=1;//初始化開關通道1
SW2=1;//初始化開關通道2
SW_Mix1=1;//初始化混控開關1
LED_NRF=0;//關掉報警燈
// LED_Battery=0;//關掉狀態燈
// Beep=0;//關掉蜂鳴器
// PCON &= ~(1<<5);//低壓檢測標志清0, 上電時標志為1
// P3M0=0x10; //P3.4 推挽輸出,要不蜂鳴器聲音太小
InitADC();//初始化ADC
// SPI_Init(); // 初始化SPI口
while(NRF24L01_Check()) // 等待檢測到NRF24L01,程序才會向下執行
{
LED_NRF=1;//狀態LED燈常亮表示NRF24L01模塊出錯。
};
NRF24L01_RT_Init(); // 配置NRF24L01為發射模式
// BEEP(250);//嗶嗶一聲表示OK
Timer0Init();//定時器0初始化
// Timer2Init();//定時器2初始化
while(1)
{
// CheckLiBattery();//檢測電池電壓
};
}
//定時器0 用來發射6通道數據給接收器
void Timer0() interrupt 1
{
GetNRFTxDate(); //查詢方式獲得4個通道ADC值和2個開關通道值
TxAllCount++; //總發射次數+1
if(NRF24L01_TxPacket(recv_buf)==TX_OK)//如果發射沒有失敗
{
TxOKCount++; //發射成功次數+1
}
if (TxAllCount==50) //發射50次以后,計算成功率
{
if (TxOKCount<40)//丟包大于80%,報警 如果接收器沒上電,也會報警
{
LED_NRF=1; //NRF模塊指示燈亮起
TimeBEEP(); //蜂鳴器報警
}
else
{
LED_NRF=0; //關報警燈
}
TxAllCount=0; //重置計數
TxOKCount=0;
}
}
//定時器2 功能就是讓蜂鳴器發出200毫秒的一個鳴叫,然后關掉。
/*void Timer2() interrupt 12
{
Time10Ms++;
if(Time10Ms<=20) //開始叫
{
Beep=1;
}
if(Time10Ms>20)//超過200毫秒停叫
{
Beep=0;
}
if(Time10Ms>40)
{
Time10Ms=0;
AUXR=0;//關掉定時器2
}
}
*/
下面是接收 程序
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define u8 unsigned char
#define u16 unsigned int
//STC12 系列新增寄存器
sfr IPH=0xb7;
sfr P4=0xc0;
sfr P4SW=0xbb;
sfr P1ASF=0x9d;
sfr P4M0=0xb4;
sfr P3M0=0xb2;
sfr P3M1=0xb1;
sfr P2M0=0x96;
sfr P0M0=0x94;
sfr ADC_CONTR=0xbc;
sfr ADC_RES=0xbd;
sfr ADC_RESL=0xbe;
sfr BRT=0x9c;
sfr AUXR=0x8e;
sfr WAKE_CLKO=0x8f;
sfr IAP_DATA=0xc2;
sfr IAP_ADDRH=0xc3;
sfr IAP_ADDRL=0xc4;
sfr IAP_CMD=0xc5;
sfr IAP_TRIG=0xc6;
sfr IAP_CONTR=0xc7;
sfr CCON = 0xD8; //PCA control register
sbit CCF0 = CCON^0; //PCA module-0 interrupt flag
sbit CCF1 = CCON^1; //PCA module-1 interrupt flag
sbit CR = CCON^6; //PCA timer run control bit
sfr CMOD = 0xD9; //PCA mode register
sfr CL = 0xE9; //PCA base timer LOW
sfr CH = 0xF9; //PCA base timer HIGH
sfr CCAPM0 = 0xDA; //PCA module-0 mode register
sfr CCAP0L = 0xEA; //PCA module-0 capture register LOW
sfr CCAP0H = 0xFA; //PCA module-0 capture register HIGH
sfr CCAPM1 = 0xDB; //PCA module-1 mode registers
sfr CCAP1L = 0xEB; //PCA module-1 capture register LOW
sfr CCAP1H = 0xFB; //PCA module-1 capture register HIGH
/*************************************************/
/* STC15W404AS寄存器補充
sfr AUXR1 = 0XA2;
sfr AUXR = 0X8E;
sfr TH2 = 0XD6;
sfr TL2 = 0XD7;
sfr P4 = 0xc0;
sfr P5 = 0xc8;
sfr P3M0=0xB2;
sfr SPSTAT = 0xCD; //
sfr SPCTL = 0xCE; //
sfr SPDAT = 0xCF; //
sfr P1M0=0x92;
//ADC
sfr ADC_CONTR = 0xBC; //帶AD系列
sfr ADC_RES = 0xBD; //帶AD系列
sfr ADC_RESL = 0xBE; //帶AD系列
sfr P1ASF = 0x9D;
sfr PCON2 = 0x97;
//定時器2
sfr T2H=0xd6;
sfr T2L=0xd7;
sfr IE2=0xaf;
#define ADC_POWER 0x80//ADC電源控制位
#define ADC_FLAG 0x10//ADC完成標志
#define ADC_START 0x08//ADC起始控制位
#define ADC_SPEEDLL 0x00//540個時鐘轉換一次
#define ADC_SPEEDL 0x20//360時鐘
#define ADC_SPEEDH 0x40//180時鐘
#define ADC_SPEEDHH 0x60//90時鐘 */
unsigned char recv_buf[6]={0,0,0,0,1,1};//NRF24模塊可以一次發射32個字節,這里只用6個,代表6個通道。
/*sbit NRF_IRQ = P5^5;
sbit NRF_MISO = P1^4;
sbit NRF_MOSI = P1^3;
sbit NRF_SCK = P1^5;
sbit NRF_CSN = P1^2;
sbit NRF_CE = P5^4; */
sbit NRF_CE = P0^1;
sbit NRF_CSN = P0^0;
sbit NRF_MISO = P0^5;
sbit NRF_MOSI = P0^2;
sbit NRF_SCK = P0^3;
sbit NRF_IRQ = P0^4;
sbit CH1=P3^2;//通道1
sbit CH2=P3^3;//通道2
sbit CH3=P3^6;//通道3
sbit CH4=P3^7;//通道4
sbit CH5=P1^0;//通道5
sbit CH6=P1^1;//通道6
u8 n=0;//定時器0的中斷次數
/********** 你可以從這里復制NRF24L01的全部代碼了 ***********/
/********** NRF24L01寄存器操作命令 ***********/
#define READ_REG 0x00 //讀配置寄存器,低5位為寄存器地址
#define WRITE_REG 0x20 //寫配置寄存器,低5位為寄存器地址
#define RD_RX_PLOAD 0x61 //讀RX有效數據,1~32字節
#define WR_TX_PLOAD 0xA0 //寫TX有效數據,1~32字節
#define FLUSH_TX 0xE1 //清除TX FIFO寄存器.發射模式下用
#define FLUSH_RX 0xE2 //清除RX FIFO寄存器.接收模式下用
#define REUSE_TX_PL 0xE3 //重新使用上一包數據,CE為高,數據包被不斷發送.
#define NRF_NOP 0xFF //空操作,可以用來讀狀態寄存器
/********** NRF24L01寄存器地址 *************/
#define CONFIG 0x00 //配置寄存器地址
#define EN_AA 0x01 //使能自動應答功能
#define EN_RXADDR 0x02 //接收地址允許
#define SETUP_AW 0x03 //設置地址寬度(所有數據通道)
#define SETUP_RETR 0x04 //建立自動重發
#define RF_CH 0x05 //RF通道
#define RF_SETUP 0x06 //RF寄存器
#define STATUS 0x07 //狀態寄存器
#define OBSERVE_TX 0x08 // 發送檢測寄存器
#define CD 0x09 // 載波檢測寄存器
#define RX_ADDR_P0 0x0A // 數據通道0接收地址
#define RX_ADDR_P1 0x0B // 數據通道1接收地址
#define RX_ADDR_P2 0x0C // 數據通道2接收地址
#define RX_ADDR_P3 0x0D // 數據通道3接收地址
#define RX_ADDR_P4 0x0E // 數據通道4接收地址
#define RX_ADDR_P5 0x0F // 數據通道5接收地址
#define TX_ADDR 0x10 // 發送地址寄存器
#define RX_PW_P0 0x11 // 接收數據通道0有效數據寬度(1~32字節)
#define RX_PW_P1 0x12 // 接收數據通道1有效數據寬度(1~32字節)
#define RX_PW_P2 0x13 // 接收數據通道2有效數據寬度(1~32字節)
#define RX_PW_P3 0x14 // 接收數據通道3有效數據寬度(1~32字節)
#define RX_PW_P4 0x15 // 接收數據通道4有效數據寬度(1~32字節)
#define RX_PW_P5 0x16 // 接收數據通道5有效數據寬度(1~32字節)
#define FIFO_STATUS 0x17 // FIFO狀態寄存器
/*————————————————————————————————————————————————————————————————————*/
/****** STATUS寄存器bit位定義 *******/
#define MAX_TX 0x10 //達到最大發送次數中斷
#define TX_OK 0x20 //TX發送完成中斷
#define RX_OK 0x40 //接收到數據中斷
/*——————————————————————————————————————————————————*/
/********* 24L01發送接收數據寬度定義 ***********/
#define TX_ADR_WIDTH 5 //5字節地址寬度
#define RX_ADR_WIDTH 5 //5字節地址寬度
#define TX_PLOAD_WIDTH 6 //32字節有效數據寬度
#define RX_PLOAD_WIDTH 6 //32字節有效數據寬度
uchar xdata TX_ADDRESS[TX_ADR_WIDTH]={0x68,0x86,0x66,0x88,0x28};
uchar xdata RX_ADDRESS[RX_ADR_WIDTH]={0x68,0x86,0x66,0x88,0x28};
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
void Delay4us() //@12.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 9;
while (--i);
}
void Delay_4us(unsigned char i)
{
while(--i)
{
Delay4us();
}
}
void delay_ms(unsigned char i)
{
while(--i)
{
Delay1ms();
}
}
void DelayMs(unsigned int i)
{
while(--i)
{
Delay1ms();
}
}
/* 初始化硬件SPI口 */
/*
void SPI_Init(void) //如果用模擬SPI,這個就不要調用了,它是開啟硬件SPI
{
SPSTAT |= 0xC0; //SPI狀態寄存器全部清0 SPIF和WCOL清0
SPCTL = 0xD0; //0xD0=11010000 ,表示SPI開啟,主機模式,SPI頻率為主頻四分之一
}
/**********************/
/* SPI數據收發函數 硬件SPI */
/*
uchar SPI_RW(uchar tr_data)
{
uchar i=0;
SPSTAT |= 0xc0; //SPI狀態寄存器全部清0 SPIF和WCOL清0
SPDAT=tr_data; //將數據放到SPI數據寄存器中
while(((SPSTAT&0x80)!=0x80)&&(i<20)) //SPSTAT&0x80 SPI數據傳輸完成標志 如果沒完成傳輸,就延時1ms
{
i++;
delay_ms(1); //20ms內沒完成,則跳出
}
return SPDAT; //返回傳輸的數據值
} */
//下面是“模擬SPI”
uchar SPI_RW(uchar byte)
{
uchar bit_ctr;
for(bit_ctr=0;bit_ctr<8;bit_ctr++) // 輸出8位
{
NRF_MOSI=(byte&0x80); // MSB TO MOSI
byte=(byte<<1); // shift next bit to MSB
NRF_SCK=1;
byte|=NRF_MISO; // capture current MISO bit
NRF_SCK=0;
}
return byte;
}
/*********************************************/
/* 函數功能:給24L01的寄存器寫值(一個字節) */
/* 入口參數:reg 要寫的寄存器地址 */
/* value 給寄存器寫的值 */
/* 出口參數:status 狀態值 */
/*********************************************/
uchar NRF24L01_Write_Reg(uchar reg,uchar value)
{
uchar status;
NRF_CSN=0; //CSN=0;
status = SPI_RW(reg);//發送寄存器地址,并讀取狀態值
SPI_RW(value);
NRF_CSN=1; //CSN=1;
return status;
}
/*************************************************/
/* 函數功能:讀24L01的寄存器值 (一個字節) */
/* 入口參數:reg 要讀的寄存器地址 */
/* 出口參數:value 讀出寄存器的值 */
/*************************************************/
uchar NRF24L01_Read_Reg(uchar reg)
{
uchar value;
NRF_CSN=0; //CSN=0;
SPI_RW(reg);//發送寄存器值(位置),并讀取狀態值
value = SPI_RW(NRF_NOP);
NRF_CSN=1; //CSN=1;
return value;
}
/*********************************************/
/* 函數功能:讀24L01的寄存器值(多個字節) */
/* 入口參數:reg 寄存器地址 */
/* *pBuf 讀出寄存器值的存放數組 */
/* len 數組字節長度 */
/* 出口參數:status 狀態值 */
/*********************************************/
uchar NRF24L01_Read_Buf(uchar reg,uchar *pBuf,uchar len)
{
uchar status,u8_ctr;
NRF_CSN=0; //CSN=0
status=SPI_RW(reg);//發送寄存器地址,并讀取狀態值
for(u8_ctr=0;u8_ctr<len;u8_ctr++)
pBuf[u8_ctr]=SPI_RW(0XFF);//讀出數據
NRF_CSN=1; //CSN=1
return status; //返回讀到的狀態值
}
/**********************************************/
/* 函數功能:給24L01的寄存器寫值(多個字節) */
/* 入口參數:reg 要寫的寄存器地址 */
/* *pBuf 值的存放數組 */
/* len 數組字節長度 */
/**********************************************/
uchar NRF24L01_Write_Buf(uchar reg, uchar *pBuf, uchar len)
{
uchar status,u8_ctr;
NRF_CSN=0;
status = SPI_RW(reg);//發送寄存器值(位置),并讀取狀態值
for(u8_ctr=0; u8_ctr<len; u8_ctr++)
SPI_RW(*pBuf++); //寫入數據
NRF_CSN=1;
return status; //返回讀到的狀態值
}
uchar NRF24L01_Write_BufData(uchar reg, uchar *pBuf, uchar len) //為避免函數重入錯誤而加的額外函數
{
uchar status,u8_ctr;
NRF_CSN=0;
status = SPI_RW(reg);//發送寄存器值(位置),并讀取狀態值
for(u8_ctr=0; u8_ctr<len; u8_ctr++)
SPI_RW(*pBuf++); //寫入數據
NRF_CSN=1;
return status; //返回讀到的狀態值
}
/*********************************************/
/* 函數功能:24L01接收數據 */
/* 入口參數:rxbuf 接收數據數組 */
/* 返回值: 0 成功收到數據 */
/* 1 沒有收到數據 */
/*********************************************/
uchar NRF24L01_RxPacket(uchar *rxbuf)
{
uchar state;
state=NRF24L01_Read_Reg(STATUS); //讀取狀態寄存器的值
NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中斷標志
if(state&RX_OK)//接收到數據
{
NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//讀取數據
NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
return 0;
}
return 1;//沒收到任何數據
}
/**********************************************/
/* 函數功能:設置24L01為發送模式 */
/* 入口參數:txbuf 發送數據數組 */
/* 返回值; 0x10 達到最大重發次數,發送失敗*/
/* 0x20 成功發送完成 */
/* 0xff 發送失敗 */
/**********************************************/
uchar NRF24L01_TxPacket(uchar *txbuf)
{
uchar state;
// uchar i;
NRF_CE=0;//CE拉低,使能24L01配置
NRF24L01_Write_BufData(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//寫數據到TX BUF 32個字節
NRF_CE=1;//CE置高,使能發送
while(NRF_IRQ==1);//等待發送完成
state=NRF24L01_Read_Reg(STATUS); //讀取狀態寄存器的值
NRF24L01_Write_Reg(WRITE_REG+STATUS,state); //清除TX_DS或MAX_RT中斷標志
if(state&MAX_TX)//達到最大重發次數
{
NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器
return MAX_TX;
}
if(state&TX_OK)//發送完成
{
return TX_OK;
}
return 0xff;//發送失敗
}
/********************************************/
/* 函數功能:檢測24L01是否存在 */
/* 返回值; 0 存在 */
/* 1 不存在 */
/********************************************/
//檢測原理就是存入NRF模塊一段數據,然后再讀出來比較一下是否一致
uchar NRF24L01_Check(void)
{
uchar check_in_buf[5]={0x11,0x22,0x33,0x44,0x55};
uchar check_out_buf[5]={0x00};
NRF_CE=0;
NRF24L01_Write_Buf(WRITE_REG+TX_ADDR, check_in_buf, 5);
NRF24L01_Read_Buf(READ_REG+TX_ADDR, check_out_buf, 5);
if((check_out_buf[0] == 0x11)&&\
(check_out_buf[1] == 0x22)&&\
(check_out_buf[2] == 0x33)&&\
(check_out_buf[3] == 0x44)&&\
(check_out_buf[4] == 0x55))return 0;
else return 1;
}
void NRF24L01_SET_TX_Mode(void)
{
NRF_CE=0;
NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0e); // 配置為無線發送模式
NRF_CE=1;
}
void NRF24L01_SET_RX_Mode(void)
{
NRF_CE=0;
NRF24L01_Write_Reg(WRITE_REG+CONFIG, 0x0f); // 配置為無線接收模式
NRF_CE=1;
}
void NRF24L01_RT_Init(void) //NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0f); 接收是0x0f,記得修改
{
NRF_CE=0;
NRF24L01_Write_Reg(WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//選擇通道0的有效數據寬度
NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
NRF24L01_Write_Buf(WRITE_REG+TX_ADDR,(uchar*)TX_ADDRESS,TX_ADR_WIDTH);//寫TX節點地址
NRF24L01_Write_Buf(WRITE_REG+RX_ADDR_P0,(uchar*)RX_ADDRESS,RX_ADR_WIDTH); //設置TX節點地址,主要為了使能ACK
NRF24L01_Write_Reg(WRITE_REG+EN_AA,0x01); //使能通道0的自動應答
NRF24L01_Write_Reg(WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址
NRF24L01_Write_Reg(WRITE_REG+SETUP_RETR,0x1a);//設置自動重發間隔時間:500us + 86us;最大自動重發次數:10次
NRF24L01_Write_Reg(WRITE_REG+RF_CH,40); //設置RF通道為125
NRF24L01_Write_Reg(WRITE_REG+RF_SETUP,0x27); //7db增益,250kbps
NRF24L01_Write_Reg(WRITE_REG+CONFIG,0x0f); //配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啟所有中斷
NRF_CE=1; //CE置高 //0x0e發射 0x0f接收
} //記得發送程序和接收程序的配置,要改0e和0f的數值,要不就要單獨要用一次發射或者接收設置。
/********** NRF24L01的全部代碼復制完成了 ***********/
void Timer0Init(void) //3毫秒@12.000MHz
{
AUXR &= 0x7F; //定時器時鐘12T模式
TMOD &= 0xF0; //設置定時器模式
TL0 = 0x48; //設置定時初值
TH0 = 0xF4; //設置定時初值
TF0 = 0; //清除TF0標志
TR0 = 1; //定時器0開始計時
ET0 = 1; //開通定時器0中斷
EA = 1; //開啟全部中斷
}
/*void Timer2Init(void) //10毫秒@12.000MHz
{
AUXR &= 0xFB; //定時器時鐘12T模式
T2L = 0xF0; //設置定時初值
T2H = 0xD8; //設置定時初值
IE2 |=0x04; //ET2=1 //允許定時器2的中斷
EA = 1; //開啟全部中斷
AUXR=0;//禁止定時器2運行
//AUXR |= 0x10; //定時器2開始計時
}
*/
void main(void)
{
u16 i; //定義一個16位的計數變量
delay_ms(100); // 延時待系統穩定
// P1M0=0x03;//P1.0 1 為強推挽,銀燕金屬舵機,STC15W408如果不強推挽,動都不動,折騰了我半夜
P3M0=0xCC;//P3.2 3 6 7為強推挽,否則一些金屬舵機會驅動不了,垃圾輝盛倒一點問題都沒
//SPI_Init(); // 初始化硬件SPI,如果你用模擬SPI口,這個就不要調用
while(NRF24L01_Check()); // 等待檢測到NRF24L01,程序才會向下執行
//如果NRF24L01模塊出錯,程序就卡死在這里了。沒引腳來做報警了,,,殘念。
NRF24L01_RT_Init(); // 配置NRF24L01為接收模式
Timer0Init();//定時器0初始化
//Timer2Init();//定時器2初始化
while(1)
{
i++; //每次累計大概1us
if(NRF_IRQ==0)//查詢方式來接收數據
{
NRF24L01_RxPacket(recv_buf);//讀取數據
i=0; //收到數據則清0累計值
}
/*if(i>60000) //累計60000次是600ms,0.6秒的樣子。
{ //超過0.6秒收不到數據,則改成平飛滑翔。聽天由命吧
//0~255對應1ms~2sm,所以125就是1.5ms,置中
recv_buf[0]=125; //副翼舵機擺臂置90°
recv_buf[1]=125; //升降舵機擺臂置90°
recv_buf[2]=0; //電調油門置0
recv_buf[3]=125; //方向舵機擺臂置90°
recv_buf[4]=1; //關掉開關通道1
recv_buf[5]=1; //關掉開關通道2
} */
}
}
//定時器0
//這里和蘿莉一樣,還是用延時吧,雖然不是同步輸出,但是舵機理論上能達到250段分級,移動很平滑
//我用100us定時器同步輸出,只有10段分級,移動不平滑,如果分成100段,定時時間太短難以控制。
void Timer0() interrupt 1 //用定時器0輪流輸出6個通道的PPM
{
n++; //定義的全局變量,用來做通道自增的
if(n==6)n=0;//輪流輸出6通道信號,整個周期18ms,反正PPM的20ms周期也不是那么嚴格
if(recv_buf[0]==0)recv_buf[0]=1; //加1,防止延時的時候,0-1=255溢出
if(recv_buf[1]==0)recv_buf[1]=1; //加1,防止延時的時候,0-1=255溢出
if(recv_buf[2]==0)recv_buf[2]=1; //加1,防止延時的時候,0-1=255溢出
if(recv_buf[3]==0)recv_buf[3]=1; //加1,防止延時的時候,0-1=255溢出
switch(n)
{ //每個通道固定1ms高電平,然后根據通道的ADC,延時4us*通道AD值的高電平,然后改成低低電平。
//通道AD值的范圍是0~255,所以延時的電平時間就是1ms+0~1ms+4*255us,即1ms~2ms高電平 255約等于250
//實際應用中,舵機用1ms~2ms的高電平來控制,而不是理論上的0.5~2.5ms
//舵機的擺臂范圍是45°~90°~135°之間移動。分別對應1ms~ 1.5ms~ 2ms高電平
case 0:CH1=1,Delay1ms(),Delay_4us(recv_buf[0]),CH1=0;break;//1通道PPM輸出 副翼
case 1:CH2=1,Delay1ms(),Delay_4us(recv_buf[1]),CH2=0;break;//2通道PPM輸出 升降
case 2:CH3=1,Delay1ms(),Delay_4us(recv_buf[2]),CH3=0;break;//3通道PPM輸出 油門
case 3:CH4=1,Delay1ms(),Delay_4us(recv_buf[3]),CH4=0;break;//4通道PPM輸出 方向
case 4: //5通道開關通道 1ms高電平是關 2ms高電平是開
{
CH5=1;
Delay1ms();//固定1ms高電平
if(recv_buf[4]==0)Delay_4us(250);//0表示通道開,1表示通道關
CH5=0;
break;
}
case 5: //6通道開關通道 1ms高電平是關 2ms高電平是開
{
CH6=1;
Delay1ms();//固定1ms高電平
if(recv_buf[5]==0)Delay_4us(250);//0表示通道開,1表示通道關
CH6=0;
break;
}
}
}
//定時器2 沒用,空著吧
//void Timer2() interrupt 12
//{
//}
|
|