nRF2401的C51驱动程序
nRF2401的调试心得
nRF2401 调试心得经过这几周的努力,nRF2401的原始样机调试基本完成了,指标到达了预期目标。
∙灵敏度很高,在-20dBm的发射功率下,可以达到10米左右的距离;在0dBm的功率下,可以超过40米。
∙整机平均功耗很低,平均工作电流约10uA(与工作时间的占空比有关)。
下面将介绍调试过程中遇到的一些问题和解决过程,希望这些可以对初学者有所帮助。
因为这是目前正在开发的一个系统,所以代码和原理图就不能公布了,这里只描述一些调试过程中的关键点,这应当也足够了。
开发环境:AVR Studio + WinAVR + SLISP硬件环境:ATmega88V + AVR Dragon + 自制并口下载线先调试发射部分(因为以前有一套用nRF24E1做的系统,但是功耗太大,没有实用化,但是正好可以用来调试),nRF2401的数据手册很简洁,很快就看完了。
但是它只有C51的例程,没有其他单片机的。
开始以为移植起来很容易,就直接写程序了。
结果运行后,没有任何效果,就是说发出的数据不对。
仔细对照C51的例子程序,没有发现有什么区别啊。
最后检查,逐步缩小范围,感觉问题可能在SPI部分。
AVR的SPI支持4种工作模式,区别在于时钟和数据的时序不同,习惯上使用方式0的最多,而我当时随便选了方式3,修改了SPI的工作模式就正常了。
发射部分可以工作了,但是新做的接收部分收不到数据。
而接收部分和发射部分的电路基本相同的,只有部分地方不一致。
将发射的程序写入到接收板,可以正常发出,说明电路没有问题,还是程序有问题。
反复对比C51的程序,终于发现是没有将CE设置为高引起的。
因为这个接收程序是从发射程序修改而来的,而发射程序只是定时发射一下,然后就进入Stand by状态,平时将CE和CS都置低了。
从这里还发现nRF2401的控制和一般芯片不同,一般芯片习惯上是高电平无效,低电平使能,nRF2401是相反的,比较容易造成习惯性错误。
基于51的无线芯片NFR24L01通信主机程序
#include<reg52.h>#include<nfr2401.h>#define uchar unsigned char#define TX_ADR_WIDTH 5 // 5 bytes TX(RX) address width#define TX_PLOAD_WIDTH 2 // 20 bytes TX payloaduchar const TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01}; // Define a static TX addressuchar rx_buf[TX_PLOAD_WIDTH];uchar tx_buf[TX_PLOAD_WIDTH]={0x12};uchar flag;sbit CE =P0^0 ;sbit CSN =P0^1 ;sbit SCK =P0^2 ;sbit MOSI =P0^3 ;sbit MISO =P0^4 ;sbit IRQ =P0^5 ;uchar spi_rw(uchar dat);uchar write_reg(uchar reg,uchar dat);uchar read_reg(uchar reg);uchar write_reg_bytes(uchar reg,uchar *pbuf,uchar x);uchar read_reg_bytes(uchar reg,uchar *pbuf,uchar x);void rx_mode();void tx_mode();void into_nfr();void delay(uchar m);//uchar cheeckRT();uchar cheeckAT();void send(uchar m);uchar spi_rw(uchar dat){uchar byt;for(byt=0;byt<8;byt++){MOSI=dat&0x80;dat=dat<<1;SCK=1;dat|=MISO;SCK=0;}return dat ; //用spi写入一个字节的时序}uchar write_reg(uchar reg,uchar dat){uchar byt;CSN=0;byt=spi_rw(reg);spi_rw(dat);return byt; //向某一个寄存器写入一个字节}uchar read_reg(uchar reg){uchar byt;CSN=0;spi_rw(reg);byt=spi_rw(0);return byt; //读某一个寄存器的内容}uchar write_reg_bytes(uchar reg,uchar *pbuf,uchar x){uchar byt,sta;CSN=0;sta=spi_rw(reg);for(byt=0;byt<x;byt++)spi_rw(*pbuf++);CSN=1;return sta; //向某一个寄存器写入x个字节}uchar read_reg_bytes(uchar reg,uchar *pbuf,uchar x){uchar byt,sta;CSN=0;sta=spi_rw(reg);for(byt=0;byt<x;byt++)pbuf[byt]=spi_rw(0);CSN=1;return sta; //从某一个寄存器读出x个字节}/**************************************************************** ***void rx_mode(){CE=0;write_reg_bytes(WRITE_REG+RX_ADDR_P0,TX_ADDR,TX_ADR_WID TH);write_reg(WRITE_REG+EN_AA,0x01);write_reg(WRITE_REG+EN_RXADDR,0x01);write_reg(WRITE_REG+RF_CH,0x40);write_reg(WRITE_REG+RX_ADDR_P0,TX_ADR_WIDTH);write_reg(WRITE_REG+RF_SETUP,0x07);write_reg(WRITE_REG+CONFIG,0x0f); //设置接收模式的寄存器CE=1;}***************************************************************** ****/void tx_mode(uchar *tx_buf){CE=0;write_reg_bytes(WRITE_REG+TX_ADDR,TX_ADDR,TX_ADR_WIDTH) ;write_reg_bytes(WRITE_REG+RX_ADDR_P0,TX_ADDR,TX_ADR_WID TH);write_reg_bytes(W_TX_PAYLAD,tx_buf,TX_PLOAD_WIDTH);write_reg(WRITE_REG+EN_AA,0x01);write_reg(WRITE_REG+EN_RXADDR,0x01);write_reg(WRITE_REG+RF_CH,0x40);write_reg(WRITE_REG+RX_ADDR_P0,TX_ADR_WIDTH);write_reg(WRITE_REG+SETUP_RETR,0x0a);write_reg(WRITE_REG+RF_SETUP,0x07);write_reg(WRITE_REG+CONFIG,0x0e);CE=1;delay(0x02);}void into_nfr(){CE=0;CSN=1;SCK=0;}uchar cheeckAT(){uchar sta;sta=spi_rw(READ_REG+STATUS);if(sta&0x30){write_reg(WRITE_REG+STATUS,0xff);CSN=0;spi_rw(FLUSH_TX);CSN=1;return (0);}elsereturn (1);}/**************************************************************** *uchar cheeckRT(){uchar sta;sta=spi_rw(READ_REG+STATUS);if(sta&0x20){CE=0 ;read_reg_bytes(R_RX_PAYLAD,rx_buf,TX_PLOAD_WIDTH);return 1;}write_reg(WRITE_REG+STATUS,0xff);return 0;}//**************************************************************** **void send(uchar m){SBUF=m;while(!TI);TI=0;}***************************************************************** ***/void allow() interrupt 4{if(RI){RI=0;tx_buf[0]=SBUF;flag=1;P1=tx_buf[0];}}void delay(uchar m){uchar i;while(m--){for(i=104;i>0;i--);}}void main(){into_nfr();TMOD=0x20;SCON=0x50;TH1=0xfd;// TR1=1;ES=1;// EA=1;// tx_mode();while(1){// if(flag==1)// {flag=0;//CE=0;//write_reg_bytes(W_TX_PAYLAD,tx_buf,TX_PLOAD_WIDTH);//CE=1;tx_mode(tx_buf);while(cheeckAT()); P2=0xf0;// }}}。
51单片机与NRF2401汇编
实验时收发双方都采用相同的电路发送方程序如下:org 0000HAJMP START;延时1/4s子程序YANSHI1S: MOV R7,#250YANSHI1S1: MOV R6,#250YANSHI1S2: NOPNOPDJNZ R6,Y ANSHI1S2DJNZ R7,YANSHI1S1RET;将58开始的单或多字节(字节数在R3中)写入芯片XIENB: MOV R0,#58HCLR P1.7 ;SCN变低XIE00: ACALL XIE1BINC R0DJNZ R3,XIE00SETB P1.7RET;;将R0所指1单元按SPI时序写入模块,调用该子程序前,应将CSN线变低;单次或多次调用完成后将CSN线变高XIE1B: MOV R2,#8MOV A,@R0XIE1B1: RLC AMOV P1.5,C ;数据送上MOSI线SETB P1.4 ;数据移入模块CLR P1.4DJNZ R2,XIE1B1RET;读芯片状态字将芯片状态字读到5FHDUZT: MOV R2,#8SETB P1.5CLR P1.7 ;CSN变低,DUZT1: SETB P1.4 ;时钟上升MOV C,P1.3 ;读入MISO线上的数据MOV A,5FHRLC A ;数据移入5FH寄存器MOV 5FH,ACLR P1.4DJNZ R2,DUZT1SETB P1.7 ;CSN变高,完成一次命令RETSTART: MOV P1,#0AFH ;模块待机MOV 58H,#20H ;准备写0寄存器MOV 59H,#0EH ;上电,发射模式MOV R3,#02HACALL XIENBMOV 58H,#21H ;01寄存器MOV 59H,#03H ;0,1通道允许自动应答MOV R3,#02HACALL XIENBMOV 58H,#22H ;02MOV 59H,#03HMOV R3,#02HACALL XIENBMOV 58H,#23H ;03寄存器MOV 59H,#03H ;5字节地址宽带MOV R3,#02HACALL XIENBMOV 58H,#24H ;04MOV 59H,#14H ;重发等待500uS,重发4次,1A则重发10次,在206c处MOV R3,#02HACALL XIENBMOV 58H,#25H ;05寄存器MOV 59H,#07H ;射频频率(汇编后在2076处)MOV R3,#02HACALL XIENBMOV 58H,#26H ;06MOV 59H,#27H ;07为1M传输速率,0dB增益,27则为250k传输速率MOV R3,#02HACALL XIENBMOV 58H,#27H ;07MOV 59H,#70H ;清模块内中断MOV R3,#02HMOV 58H,#2AH ;0A寄存器(通道0)MOV 59H,#02H ;配置地址MOV 5AH,#3AHMOV 5BH,#39HMOV 5CH,#38HMOV 5DH,#37HMOV R3,#06HACALL XIENBMOV 58H,#30H ;10寄存器MOV R3,#06H ;发送地址ACALL XIENBMOV 58H,#2BH ;0B寄存器(通道1)MOV 59H,#01H ;本机地址MOV R3,#06HACALL XIENBMOV 58H,#31H ;11寄存器MOV 59H,#10H ;0通道有效数据宽带16字节MOV R3,#02HACALL XIENBMOV 58H,#32H ;12寄存器MOV 59H,#10H ;1通道有效数据宽度16字节MOV R3,#02HACALL XIENBXIEFS: MOV 58H,#0A0H ;写发送数据到芯片MOV R0,#58HMOV R3,#10HCLR P1.7ACALL XIE1BMOV R0,#70HXIEXUN: ACALL XIE1BINC R0DJNZ R3,XIEXUNSETB P1.7SETB P1.6 ;启动发射MOV R7,#5DJNZ R7,$CLR P1.6JB P3.2,$cpl p1.0ACALL DUZT ;读状态寄存器MOV 58H,#27H ;07MOV 59H,#70H ;清中断MOV R3,#02HMOV 58H,#0E1H ;清模块发送缓冲区MOV R3,#01HACALL XIENBACALL YANSHI1SSJMP XIEFSend接收端程序:org 0000HAJMP STARTorg 0003HAJMP EXINT0;延时1/4s子程序YANSHI1S: MOV R7,#250YANSHI1S1: MOV R6,#250YANSHI1S2: NOPNOPDJNZ R6,YANSHI1S2DJNZ R7,YANSHI1S1RET;将58开始的单或多字节(字节数在R3中)写入芯片XIENB: MOV R0,#58HCLR P1.7 ;SCN变低XIE00: ACALL XIE1BINC R0DJNZ R3,XIE00SETB P1.7RET;;将R0所指1单元按SPI时序写入模块,调用该子程序前,应将CSN线变低;单次或多次调用完成后将CSN线变高XIE1B: MOV R2,#8MOV A,@R0XIE1B1: RLC AMOV P1.5,C ;数据送上MOSI线SETB P1.4 ;数据移入模块CLR P1.4DJNZ R2,XIE1B1RET;按SPI时序读模块一字节入单片机R0所指单元,调用该子程序前,应将CSN线变低;单次或多次调用完成后将CSN线变高DU1B: MOV R2,#8DU1B1: SETB P1.4MOV C,P1.3RLC ACLR P1.4DJNZ R2,DU1B1MOV @R0,ARET;按SPI时序读模块接收缓冲区数据入单片机R0所指单元,字节数在R3中DUNB: PUSH 00HMOV 58H,#61H ;写一字节命令MOV R0,#58HCLR P1.7ACALL XIE1BPOP 00H ;R0指向接收缓冲区首地址DUXUN: ACALL DU1BINC R0DJNZ R3,DUXUNSETB P1.7RET;读芯片状态字将芯片状态字读到5FHDUZT: MOV R2,#8SETB P1.5 ;输入芯片1CLR P1.7 ;CSN变低,DUZT1: SETB P1.4 ;时钟上升MOV C,P1.3 ;读入MISO线上的数据MOV A,5FHRLC A ;数据移入5FH寄存器MOV 5FH,ACLR P1.4DJNZ R2,DUZT1SETB P1.7 ;CSN变高,完成一次命令RETSTART: MOV P1,#0AFH ;模块待机SETB 0A8H ;允许外部中断0CLR 88H ;电平触发SETB 0B8H ;高优先级SETB 0AFH ;CPU开中断MOV 58H,#20H ;准备写0寄存器MOV 59H,#0FH ;上电,接收模式(发射时,设置为0EH)MOV R3,#02HACALL XIENBMOV 58H,#21H ;01寄存器MOV 59H,#03H ;0,1通道允许自动应答MOV R3,#02HACALL XIENBMOV 58H,#22H ;02MOV 59H,#03H ;允许0,1通道接收MOV R3,#02HACALL XIENBMOV 58H,#23H ;03寄存器MOV 59H,#03H ;5字节地址宽带MOV R3,#02HACALL XIENBMOV 58H,#24H ;04MOV 59H,#14H ;重发等待500uS,重发4次MOV R3,#02HACALL XIENBMOV 58H,#25H ;05寄存器MOV 59H,#07H ;射频频率MOV R3,#02HACALL XIENBMOV 58H,#26H ;06MOV 59H,#27H ;设置为07为1M传输速率,0dB增益(若为27,则是250kpbs,0dB)MOV R3,#02HACALL XIENBMOV 58H,#27H ;07MOV 59H,#70H ;清模块内中断MOV R3,#02HACALL XIENBMOV 58H,#2AH ;0A寄存器(通道0)MOV 59H,#01H ;配置地址(对方地址)MOV 5AH,#3AHMOV 5BH,#39HMOV 5CH,#38HMOV 5DH,#37HMOV R3,#06HACALL XIENBMOV 58H,#30H ;10寄存器MOV R3,#06H ;发送地址ACALL XIENBMOV 58H,#2BH ;0B寄存器(通道1)MOV 59H,#02H ;本机地址MOV R3,#06HACALL XIENBMOV 58H,#31H ;11寄存器MOV 59H,#10H ;0通道有效数据宽带16字节MOV R3,#02HACALL XIENBMOV 58H,#32H ;12寄存器MOV 59H,#10H ;1通道有效数据宽度16字节MOV R3,#02HACALL XIENBSETB P1.6 ;启动接收HALT: SJMP HALTEXINT0: PUSH ACCPUSH PSWACALL DUZT ;读状态寄存器MOV 58H,#27H ;07MOV 59H,#70H ;清中断MOV R3,#02HACALL XIENBMOV R0,#60H ;读接收数据到60H到6FHMOV R3,#10HACALL DUNBCPL P1.0FANHUI: POP PSWPOP ACCRETIend。
无线模块2401调试方法(C51)
//*************************************SPI(nRF24L01)寄存器地址**************************************************** #define CONFIG #define EN_AA #define EN_RXADDR #define SETUP_AW #define SETUP_RETR #define RF_CH #define RF_SETUP #define STATUS #define OBSERVE_TX #define CD #define RX_ADDR_P0 #define RX_ADDR_P1 #define RX_ADDR_P2 #define RX_ADDR_P3 #define RX_ADDR_P4 #define RX_ADDR_P5 #define TX_ADDR #define RX_PW_P0 #define RX_PW_P1 #define RX_PW_P2 #define RX_PW_P3 #define RX_PW_P4 #define RX_PW_P5 #define FIFO_STATUS 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 // 配置收发状态,CRC 校验模式以及收发状态响应方式 // 自动应答功能设置 // 可用信道设置 // 收发地址宽度设置 // 自动重发功能设置 // 工作频率设置 // 发射速率、功耗功能设置 // 状态寄存器 // 发送监测功能 // 地址检测 // 频道 0 接收数据地址 // 频道 1 接收数据地址 // 频道 2 接收数据地址 // 频道 3 接收数据地址 // 频道 4 接收数据地址 // 频道 5 接收数据地址 // 发送地址寄存器 // 接收频道 0 接收数据长度 // 接收频道 0 接收数据长度 // 接收频道 0 接收数据长度 // 接收频道 0 接收数据长度 // 接收频道 0 接收数据长度 // 接收频道 0 接收数据长度 // FIFO 栈入栈出状态寄存器设置
无线模块NRF24L01基于C51单片机双向通讯C语言程序(中文详解)
#include <reg52.h>#include <intrins.h>/********************************************************** *****************************//* NRF24L01 地管脚定义,以及在本程序中地应用,VCC接3.3V 电源,可以通过5V用电压转换芯片/*得到,NC 管脚可以接可以不接,暂时没用途.本程序应用于51或者52单片机,是两个模块进行通讯/*成功地简单指示,现象是:模块1地 KEY1 对应模块1地LED1 和模块2地LED3 ,模块1地 KEY2 对应模/*块1地LED2 和模块2地LED4,发过来也对应./********************************************************** *****************************/typedef unsigned char uchar;typedef unsigned char uint;/************************************NRF24L01端口定义***********************************/sbit NC =P2^0; //没用,不接也可sbit MISO =P2^5; //数字输出(从 SPI 数据输出脚)sbit MOSI =P2^4; //数字输入(从 SPI 数据输入脚)sbit SCK =P1^7; //数字输入(SPI 时钟)sbit CE =P2^1; //数字输入(RX 或 TX 模式选择)sbit CSN =P2^2; //数字输入(SPI片选信号)sbit IRQ =P2^6; //数字输入(可屏蔽中断)/************************************按键***********************************************/sbit KEY1=P3^3;//按键S1sbit KEY2=P3^2;//按键S2/************************************数码管位选******************************************/sbit led1=P1^0; //LED0sbit led2=P1^1; //LED1sbit led3 =P1^2; //LED2sbit led4 =P1^3; //LED3sbit led5 =P1^4; //LED4/*********************************************NRF24L01***********************************/#define TX_ADR_WIDTH 5 // 5 uints TX address width 发送地址宽度#define RX_ADR_WIDTH 5 // 5 uints RX address width 接收地址宽度#define TX_PLOAD_WIDTH 20 // 20 uints TX payload 有效载荷装载货物#define RX_PLOAD_WIDTH 20 // 20 uints TX payloaduint const TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //本地地址uint const RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //接收地址/***************************************NRF24L01寄存器指令*******************************/#define READ_REG 0x00 // 读寄存器指令#define WRITE_REG 0x20 // 写寄存器指令#define RD_RX_PLOAD 0x61 // 读取接收数据指令#define WR_TX_PLOAD 0xA0 // 写待发数据指令#define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令#define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令#define REUSE_TX_PL 0xE3 // 定义重复装载数据指令#define NOP 0xFF // 保留/*************************************SPI(nRF24L01)寄存器地址***********************/#define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式#define EN_AA 0x01 // 自动应答功能设置#define EN_RXADDR 0x02 // 可用信道设置#define SETUP_AW 0x03 // 收发地址宽度设置#define SETUP_RETR 0x04 // 自动重发功能设置#define RF_CH 0x05 // 工作频率设置#define RF_SETUP 0x06 // 发射速率.功耗功能设置#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接收数据长度#define RX_PW_P1 0x12 // 接收频道0接收数据长度#define RX_PW_P2 0x13 // 接收频道0接收数据长度#define RX_PW_P3 0x14 // 接收频道0接收数据长度#define RX_PW_P4 0x15 // 接收频道0接收数据长度#define RX_PW_P5 0x16 // 接收频道0接收数据长度#define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置/*************************************函数声明****************************************/void Delay(unsigned int s); //大延时void inerDelay_us(unsigned char n); //小延时void init_NRF24L01(void); //NRF24L01 初始化uint SPI_RW(uint dat); //根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01读出一字节uchar SPI_Read(uchar reg); //从reg寄存器读一字节void SetRX_Mode(void); //数据接收配置uint SPI_RW_Reg(uchar reg, uchar value); //写数据value到reg寄存器uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); //从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); //把pBuf缓存中地数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址unsigned char nRF24L01_RxPacket(unsigned char* rx_buf);//数据读取后放入rx_buf接收缓冲区中void nRF24L01_TxPacket(unsigned char * tx_buf);//发送 tx_buf中数据/*****************************************长延时*****************************************/void Delay(unsigned int s){unsigned int i;for(i=0; i<s; i++);for(i=0; i<s; i++);}/********************************************************** ********************************/uint bdata sta; //状态标志sbit RX_DR =sta^6; //RX_DR 为 sta 地第六位sbit TX_DS =sta^5; //TX_DS 为 sta 地第五位sbit MAX_RT =sta^4; //MAX_RT 为 sta 地第四位/********************************************************** ********************************//*延时函数/********************************************************** ********************************/void inerDelay_us(unsigned char n) //延时,us 级{for(;n>0;n--)_nop_();}/********************************************************** ******************************//*NRF24L01初始化/********************************************************** *****************************/void init_NRF24L01(void){inerDelay_us(100);CE=0; // 芯片使能CSN=1; // 禁止 SPISCK=0; // SPI时钟置低SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS,TX_ADR_WIDTH); // 写本地地址SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS,RX_ADR_WIDTH); // 写接收端地址SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 频道0自动ACK应答允许SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道0,如果需要多频道可以参考Page21SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 设置信道工作为2.4GHZ,收发必须一致SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //设置发射速率为1MHZ,发射功率为最大值0dB}/********************************************************** ******************************************//*函数:uint SPI_RW(uint uchar)/*功能:NRF24L01地SPI写时序-----根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01 读出一字节/********************************************************** ******************************************/uint SPI_RW(uint dat){uint i;for(i=0;i<8;i++) // 循环8次{MOSI = (dat & 0x80); // dat地最高位输出到MOSI MSB to MOSIdat = (dat << 1); // 从右向左进一位shift next bit into MSB..SCK = 1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据Set SCK high..dat |= MISO; //读MISO到 dat 最低位 capture current MISO bitSCK = 0; // SCK置低..then set SCK low again}return(dat); //返回读出地一字节 return read dat}/********************************************************** ******************************************/*函数:uchar SPI_Read(uchar reg)/*功能:NRF24L01地SPI时序-----------从reg寄存器读一字节/********************************************************** ******************************************/uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0; //CSN置低,开始传输数据CSN low, initialize SPI communication...SPI_RW(reg); //选择寄存器 Select register to read from..reg_val = SPI_RW(0); //然后从该寄存器读数据 ..then read registervalueCSN = 1; //CSN拉高,结束数据传输CSN high, terminate SPI communicationreturn(reg_val); //返回寄存器数据 return register value}/********************************************************** ******************************************//*功能:NRF24L01读写寄存器函数/*描述:写数据value到reg寄存器/********************************************************** ******************************************/uint SPI_RW_Reg(uchar reg, uchar value){uchar status;CSN = 0; // CSN置低,开始传输数据CSN low, init SPI transactionstatus = SPI_RW(reg); // 选择寄存器,同时返回状态字select registerSPI_RW(value); // 然后写数据到该寄存器 ..and write value to it..CSN = 1; // CSN拉高,结束数据传输CSN high againreturn(status); // 返回状态寄存器 return nRF24L01 status uchar}/********************************************************** ******************************************//*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars) /*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据地个数/*描述: 从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址/********************************************************** ******************************************/uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,i;CSN = 0; //CSN置低,开始传输数据 Set CSN low, init SPI tranactionstatus = SPI_RW(reg); //选择寄存器,同时返回状态字Select register to write to and read status uchar for(i=0;i<uchars;i++)pBuf[i] = SPI_RW(0); //逐个字节从nRF24L01读出CSN = 1; //CSN拉高,结束数据传输return(status); //返回状态寄存器return nRF24L01 status uchar}/********************************************************** ***********************************************/*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据地个数/*描述:把pBuf缓存中地数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址/********************************************************** ***********************************************/uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,i;CSN = 0; //CSN置低,开始传输数据status = SPI_RW(reg); //选择寄存器,同时返回状态字inerDelay_us(10);for(i=0; i<uchars; i++)SPI_RW(*pBuf++); //逐个字节写入nRF24L01CSN = 1; //CSN拉高,结束数据传输return(status); //返回状态寄存器}/********************************************************** ******************************************//*函数:void SetRX_Mode(void)/*功能:数据接收配置/********************************************************** ******************************************/void SetRX_Mode(void){CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);//CRC使能,16位CRC 校验,上电,接收模式CE = 1; // 拉高CE启动接收设备inerDelay_us(130);}/********************************************************** ********************************************//*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf) /*功能:数据读取后放入rx_buf接收缓冲区中/********************************************************** ********************************************/unsigned char nRF24L01_RxPacket(unsigned char* rx_buf){unsigned char revale=0;sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况if(RX_DR) // 判断是否接收到数据{CE = 0; //SPI使能SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO bufferrevale =1; //读取数据完成标志}SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志return revale;}/********************************************************** *************************************************/*函数:void nRF24L01_TxPacket(unsigned char * tx_buf)/*功能:发送 tx_buf中数据/********************************************************** ************************************************/void nRF24L01_TxPacket(unsigned char * tx_buf){CE=0; //StandBy I模式SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS,TX_ADR_WIDTH); // 装载接收端地址SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH);// 装载数据SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ 收发完成中断响应,16位CRC,主发送CE=1; //置高CE,激发数据发送}/************************************主函数*********************************************************** */void main(void){unsigned char tf =0;unsigned char TxBuf[20]={0}; // 要发送地数组unsigned char RxBuf[20]={0}; // 接收地数据数组init_NRF24L01() ; //模块初始化led1=1;led2=1;led3 =1;led4 =1; //led 灯关闭Delay(1000);while(1){if(KEY1 ==0 ) //按键 1 按下{TxBuf[1] = 1 ; //赋值tf = 1 ;led1=0; //本地led 灯闪烁led1=1;Delay(200);}if(KEY2 ==0 ) //按键 2 按下{TxBuf[2] =1 ; //赋值tf = 1 ;led2=0; //本地led 灯闪烁Delay(200);led2=1;Delay(200);}if (tf==1) //有键按下{nRF24L01_TxPacket(TxBuf); //发送数据 Transmit Tx buffer dataTxBuf[1] = 0x00; //清零TxBuf[2] = 0x00;tf=0;Delay(1000);}SetRX_Mode(); //设置成接受模式RxBuf[1] = 0x00; //接收地数组相应位清零RxBuf[2] = 0x00;Delay(1000);nRF24L01_RxPacket(RxBuf); //接收数据if(RxBuf[1]|RxBuf[2]){if( RxBuf[1]==1){led3=RxBuf[0];}if( RxBuf[2]==1){led4=RxBuf[4];}Delay(3000); //old is '1000'}RxBuf[1] = 0x00; //清零RxBuf[2] = 0x00;led3=1; //关灯led4=1;}}本程序存在地问题:反应不够灵敏,当在按键1和按键2之间切换地时候,对方地灯闪烁会有一定地延时,另外本程序没有消除按键地抖动.对部分函数地解释:uint SPI_RW(uint dat)最基本地函数,完成 GPIO模拟 SPI 地功能.将输出字节(MOSI)从 MSB 循环输出,同时将输入字节(MISO)从 LSB 循环移入.上升沿读入,下降沿输出. (从 SCK被初始化为低电平可以判断出)uchar SPI_Read(uchar reg); //从reg寄存器读一字节读取寄存器值地函数:基本思路就是通过 READ_REG命令(也就是 0x00+寄存器地址) ,把寄存器中地值读出来.对于函数来说也就是把 reg 寄存器地值读到reg_val 中去.uint SPI_RW_Reg(uchar reg, uchar value); //写数据value到reg寄存器寄存器访问函数:用来设置 24L01 地寄存器地值.基本思路就是通过 WRITE_REG命令(也就是 0x20+寄存器地址)把要设定地值写到相应地寄存器地址里面去,并读取返回值.对于函数来说也就是把 value值写到 reg 寄存器中.需要注意地是,访问 NRF24L01 之前首先要 enable 芯片(CSN=0;) ,访问完了以后再 disable芯片(CSN=1;).uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); //从reg寄存器读出bytes个字节,通常用来//读取接收通道数据或接收/发送地址接收缓冲区访问函数:主要用来在接收时读取 FIFO 缓冲区中地值.基本思路就是通过READ_REG命令把数据从接收 FIFO(RD_RX_PLOAD)中读出并存到数组里面去.uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); //把pBuf缓存中地数据写入到nRF24L01,通常//用来写入发发射缓冲区访问函数:主要用来把数组里地数放到发射 FIFO缓冲区中.基本思路就是通过WRITE_REG命令把数据存到发射 FIFO(WR_TX_PLOAD)中去.Tx 模式初始化过程1)写 Tx 节点地地址 TX_ADDR2)写 Rx 节点地地址(主要是为了使能 Auto Ack) RX_ADDR_P0 3)使能 AUTO ACK EN_AA4)使能 PIPE 0 EN_RXADDR5)配置自动重发次数 SETUP_RETR6)选择通信频率 RF_CH7)配置发射参数(低噪放大器增益.发射功率.无线速率) RF_SETUP 8 ) 选择通道0 有效数据宽度 Rx_Pw_P09)配置 24L01 地基本参数以及切换工作模式 CONFIG.Rx 模式初始化过程:初始化步骤 24L01 相关寄存器1)写 Rx 节点地地址 RX_ADDR_P02)使能 AUTO ACK EN_AA3)使能 PIPE 0 EN_RXADDR4)选择通信频率 RF_CH5) 选择通道0 有效数据宽度 Rx_Pw_P06)配置发射参数(低噪放大器增益.发射功率.无线速率) RF_SETUP 7)配置 24L01 地基本参数以及切换工作模式 CONFIG.。
NRF2401在51单片机上的接收与发送程序
//这是在网上收集的程序,版权归原作者所有NRF2401程序(接收部分)jxj2e1v8v 发表于2008-3-31 1:56:00#include <reg52.h>#include<intrins.h>// 常量定义#define uchar unsigned char#define uint unsigned int#define BYTE_BIT0 0x01#define BYTE_BIT1 0x02#define BYTE_BIT2 0x04#define BYTE_BIT3 0x08#define BYTE_BIT4 0x10#define BYTE_BIT5 0x20#define BYTE_BIT6 0x40#define BYTE_BIT7 0x80//---------------------------位变量定义----------------------------------------bdata uchar DATA_BUF; //用于ByteRead和ByteWrite 函数#define DATA7 ((DA TA_BUF&BYTE_BIT7)!=0)#define DATA0 ((DATA_BUF&BYTE_BIT0)!=0)uchar RxBuf[28];// ------------------------------<RF2401_Pins 对应引脚> -----------------------sbit PWR_UP = P1^0;sbit CE = P1^1;// sbit DR2 = P3^2; //暂时没有用到// sbit CLK2 = P1^2;// sbit OUT2 = P1^4;sbit CS = P1^3;sbit DR1 = P3^3;sbit CLK1 = P1^7;sbit DATA = P1^5;//sbit LED0 = P3^4;//sbit LED1 = P3^5;//sbit KEY0 = P3^0;//sbit KEY1 = P3^1;//-------------------------------------------------------------------------------unsigned char TxAddress[4]={0xcc,0xcc,0xcc,0xcc}; //发送地址//---------------------<nRF-Configuration-Register 配置信息>------------------------------//芯片测试用,无需修改#define TEST_2 0x8E // MSB D143-D136#define TEST_1 0x08 // D135~D128#define TEST_0 0x1c // D127~D120// 注意DATAx_W+ADDRx_W+CRC 的值必须小于256!单个数据包的大小必须小于32字节(256位)#define DATA2_W 0x10 //未用到--0x10=2字节//频道2发送/接受数据长度(单位:Bit)#define DATA1_W 0xE0 //28字节16 位//频道1发送/接受数据长度(单位:Bit)//频道2接收地址<-频道2未使用#define ADDR2_4 0x00#define ADDR2_3 0x1c#define ADDR2_2 0xcc#define ADDR2_1 0xcc#define ADDR2_0 0xcc// 频道1接收地址(当前模块地址) <-只是用频道1#define ADDR1_4 0x00#define ADDR1_3 0xcc#define ADDR1_2 0xcc#define ADDR1_1 0xcc#define ADDR1_0 0xcc//接收地址位置设置--CRC设置#define ADDR_W 0x10 //0x10 =2字节//发送/接收地址宽度(单位:Bit)#define CRC_L 0x1 //CRC模式0:8位1:16位#define CRC_EN 0x1 //CRC校验0:禁止1:启用//频道设置--发送方式设置--速率设置--频率设置#define RX2_EN 0x0 //双频道功能0:禁用1:启用#define CM 0x1 //0:Direct Mode 1: Shockburst Mode#define RFDR_SB 0x1 //传输速率0:250k 1: 1M (250k比1M传输距离远)#define XO_F 0x3 //16M D12 D11 D10 确定5种频率#define RF_PWR 0x3 //信号发射功率---0DB//#define RF_CH 0x2 //Channal 频率设置Channel=2400MHz+RF_CH*1.0MHz#define RXEN 0x1 //0:TX 1:RX//<将设置信息组合成每个字节的数据信息#define RFconfig_Bit0 TEST_2#define RFconfig_Bit1 TEST_1#define RFconfig_Bit2 TEST_0#define RFconfig_Bit3 DA TA2_W#define RFconfig_Bit4 DA TA1_W#define RFconfig_Bit5 ADDR2_4#define RFconfig_Bit6 ADDR2_3#define RFconfig_Bit7 ADDR2_2#define RFconfig_Bit8 ADDR2_1#define RFconfig_Bit9 ADDR2_0#define RFconfig_Bit10 ADDR1_4#define RFconfig_Bit11 ADDR1_3#define RFconfig_Bit12 ADDR1_2#define RFconfig_Bit13 ADDR1_1#define RFconfig_Bit14 ADDR1_0#define RFconfig_Bit15 (ADDR_W<<2|CRC_L<<1|CRC_EN)#define RFconfig_Bit16 (RX2_EN<<7|CM<<6|RFDR_SB<<5|XO_F<<2|RF_PWR)#define RFconfig_Bit17 (RF_CH<<1|RXEN)//通过宏定义将18字节的寄存器参数按照各个功能分解,参照DATASHHETuchar code nRF2401_Conf[18]={RFconfig_Bit0,RFconfig_Bit1,RFconfig_Bit2,RFconfig_Bit3,RFconfig_Bit4,RFconfig_Bit5,RFconfig_Bit6,RFconfig_Bit7,RFconfig_Bit8,RFconfig_Bit9, RFconfig_Bit10,RFconfig_Bit11,RFconfig_Bit12,RFconfig_Bit13,RFconfig_Bit14, RFconfig_Bit15,RFconfig_Bit16,RFconfig_Bit17};//------------------------------------------函数申明------------------------------------------void Delay_us(uchar n);void DoClock();void Delay_ms(uchar n);unsigned char Spi_ByteRead(void);void Spi_ByteWrite(unsigned char send);void Config2401(void);void SetTxMode(void);void nRF2401_TxPacket(uchar TxBuf[]);//--------------------------------11.0592M晶振n=100 868us 左右------------------------------- void Delay_us(uchar n){uint i;for(i=0;i<n;i++);}//------------------------------------------ -----------------------------------------void Delay_ms(uchar n){unsigned int i,j,k;for(i=0;i<n;i++){for(k=0;k<5;k++){for(j=0;j<200;j++);}}}//--------------------------SPI读------------------------------------------ unsigned char Spi_ByteRead(void){unsigned char i = 0;for (i=0; i<8; i++){DATA_BUF = DA TA_BUF << 1;CLK1 = 1;DATA = 1; //设置为输入状态if (DATA) //读取最高位,保存至最末尾,通过左移位完成整个字节{DA TA_BUF |= BYTE_BIT0;}else{DA TA_BUF &= ~BYTE_BIT0;}CLK1 = 0;}return DATA_BUF;}//----------------------------------SPI写----------------------------------------- void Spi_ByteWrite(unsigned char send){unsigned char i;DATA_BUF = send;CLK1 = 0;for (i=0; i<8; i++){if (DATA7) //总是发送最高位{DA TA = 1;}else{DA TA = 0;}CLK1 = 1;DATA_BUF = DA TA_BUF << 1;CLK1 = 0;}}//-----------------------------配置2401-------------------------------------------- void Config2401(void){uint i;uchar variable1;PWR_UP=1; //上电CE=0;CS=1; //使RF2401进入配置方式Delay_ms(3); //从上电到进入配置模式需要3ms的延时(最少)for(i=0;i<18;i++) //输入3个测试字节15个配置字节共18Byte{variable1=nRF2401_Conf[i];Spi_ByteWrite(variable1);}CS=0; //Disable CS -----standby modeDATA=0;Delay_us(100);}/*//--------------------------------设置为发送模式----------------------------void SetTxMode(void){//-------------------------------设置为配置模式---------------------------------- PWR_UP=1; //上电CE=0;CS=1; //进入配置模式Delay_us(100);DATA=0; //配置寄存器0字节RXEN 设置为0: 发送模式CLK1=1;CLK1=0;//----------------------------设置为Activemodes(TX)------------------------------ CS=0;CE=1; //set standby modeDelay_us(100);}//--------------------------------nRF 数据发送函数-------------------------------- void nRF2401_TxPacket(){int i;uchar variable2;CE=1;for(i=0;i<2;i++) //写入接受地址(按字节对齐){variable2=TxAddress[i];Spi_ByteWrite(variable2);}for(i=0;i<(28);i++) //写入接受地址(按字节对齐){variable2=TxBuf[i];Spi_ByteWrite(variable2);}CE=0; //CE配置低使发送有效Delay_us(100); //时钟信号高电平有效}*/void SetRxMode(void){PWR_UP=1; //上电CE=0;CS=1; //进入配置模式Delay_us(100);DATA=1; //配置寄存器0字节RXEN 设置为0: 发送模式CLK1=1;CLK1=0;//----------------------------设置为Activemodes(TX)------------------------------ CS=0;CE=1; //set standby modeDelay_us(100);}void nRF2401_RxPacket(){int i;DR1=1;if(DR1==1){for(i=0;i<(28);i++) //写入接受地址(按字节对齐){RxBuf[i]=Spi_ByteRead();}}CE=0; //CE配置低使发送有效Delay_us(100); //时钟信号高电平有效}//---------------------------串口初始化----------------------------------void StartUART( void ){ //波特率4800SCON = 0x50;TMOD = 0x20;TH1 = 0xFA;TL1 = 0xFA;PCON = 0x00;TR1 = 1;}//--------------------------串口接收函数---------------------------------- void R_S_Byte(uchar R_Byte){SBUF = R_Byte;while( TI == 0 ); //查询法TI = 0;}//------------------------------------主函数--------------------------------------- main(){uchar i;Config2401();Delay_us(100);StartUART();while(1){SetRxMode();nRF2401_RxPacket();for(i=0;i<28;i++){R_S_Byte( RxBuf[i]);}}}NRF2401程序(发送部分)jxj2e1v8v 发表于2008-3-31 1:53:00#include <reg52.h>#include<intrins.h>// 常量定义#define uchar unsigned char#define uint unsigned int#define BYTE_BIT0 0x01#define BYTE_BIT1 0x02#define BYTE_BIT3 0x08#define BYTE_BIT4 0x10#define BYTE_BIT5 0x20#define BYTE_BIT6 0x40#define BYTE_BIT7 0x80//---------------------------位变量定义----------------------------------------bdata uchar DATA_BUF; //用于ByteRead和ByteWrite 函数#define DATA7 ((DA TA_BUF&BYTE_BIT7)!=0)#define DATA0 ((DATA_BUF&BYTE_BIT0)!=0)uchar TxBuf[28]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,};// ------------------------------<RF2401_Pins 对应引脚> -----------------------sbit PWR_UP = P1^0;sbit CE = P1^1;// sbit DR2 = P3^2; //暂时没有用到// sbit CLK2 = P1^2;// sbit OUT2 = P1^4;sbit CS = P1^3;sbit DR1 = P3^3;sbit CLK1 = P1^7;sbit DATA = P1^5;////sbit LED0 = P3^4;//sbit LED1 = P3^5;//sbit KEY0 = P3^0;//sbit KEY1 = P3^1;//-------------------------------------------------------------------------------unsigned char TxAddress[4]={0xcc,0xcc,0xcc,0xcc}; //发送地址//---------------------<nRF-Configuration-Register 配置信息>------------------------------//芯片测试用,无需修改#define TEST_2 0x8E // MSB D143-D136#define TEST_1 0x08 // D135~D128#define TEST_0 0x1c // D127~D120// 注意DATAx_W+ADDRx_W+CRC 的值必须小于256!单个数据包的大小必须小于32字节(256位)#define DATA2_W 0x10 //未用到--0x10=2字节//频道2发送/接受数据长度(单位:Bit)#define DATA1_W 0xE0 //28字节16 位//频道1发送/接受数据长度(单位:Bit)//频道2接收地址<-频道2未使用#define ADDR2_4 0x00#define ADDR2_2 0xcc#define ADDR2_1 0xcc#define ADDR2_0 0xcc// 频道1接收地址(当前模块地址) <-只是用频道1#define ADDR1_4 0x00#define ADDR1_3 0xcc#define ADDR1_2 0xcc#define ADDR1_1 0xcc#define ADDR1_0 0xcc//接收地址位置设置--CRC设置#define ADDR_W 0x10 //0x10 =2字节//发送/接收地址宽度(单位:Bit)#define CRC_L 0x1 //CRC模式0:8位1:16位#define CRC_EN 0x1 //CRC校验0:禁止1:启用//频道设置--发送方式设置--速率设置--频率设置#define RX2_EN 0x0 //双频道功能0:禁用1:启用#define CM 0x1 //0:Direct Mode 1: Shockburst Mode#define RFDR_SB 0x1 //传输速率0:250k 1: 1M (250k比1M传输距离远) #define XO_F 0x3 //16M D12 D11 D10 确定5种频率#define RF_PWR 0x3 //信号发射功率---0DB//#define RF_CH 0x2 //Channal 频率设置Channel=2400MHz+RF_CH*1.0MHz#define RXEN 0x0 //0:TX 1:RX//<将设置信息组合成每个字节的数据信息#define RFconfig_Bit0 TEST_2#define RFconfig_Bit1 TEST_1#define RFconfig_Bit2 TEST_0#define RFconfig_Bit3 DA TA2_W#define RFconfig_Bit4 DA TA1_W#define RFconfig_Bit5 ADDR2_4#define RFconfig_Bit6 ADDR2_3#define RFconfig_Bit7 ADDR2_2#define RFconfig_Bit8 ADDR2_1#define RFconfig_Bit9 ADDR2_0#define RFconfig_Bit10 ADDR1_4#define RFconfig_Bit11 ADDR1_3#define RFconfig_Bit12 ADDR1_2#define RFconfig_Bit13 ADDR1_1#define RFconfig_Bit14 ADDR1_0#define RFconfig_Bit15 (ADDR_W<<2|CRC_L<<1|CRC_EN)#define RFconfig_Bit16 (RX2_EN<<7|CM<<6|RFDR_SB<<5|XO_F<<2|RF_PWR)#define RFconfig_Bit17 (RF_CH<<1|RXEN)//通过宏定义将18字节的寄存器参数按照各个功能分解,参照DATASHHET uchar code nRF2401_Conf[18]={RFconfig_Bit0,RFconfig_Bit1,RFconfig_Bit2,RFconfig_Bit3,RFconfig_Bit4,RFconfig_Bit5,RFconfig_Bit6,RFconfig_Bit7,RFconfig_Bit8,RFconfig_Bit9, RFconfig_Bit10,RFconfig_Bit11,RFconfig_Bit12,RFconfig_Bit13,RFconfig_Bit14, RFconfig_Bit15,RFconfig_Bit16,RFconfig_Bit17};//------------------------------------------函数申明------------------------------------------void Delay_us(uchar n);void DoClock();void Delay_ms(uchar n);unsigned char Spi_ByteRead(void);void Spi_ByteWrite(unsigned char send);void Config2401(void);void SetTxMode(void);void nRF2401_TxPacket(uchar TxBuf[]);//--------------------------------11.0592M晶振n=100 868us 左右------------------------------- void Delay_us(uchar n){uint i;for(i=0;i<n;i++);}//------------------------------------------ -----------------------------------------void Delay_ms(uchar n){unsigned int i,j,k;for(i=0;i<n;i++){for(k=0;k<5;k++){for(j=0;j<200;j++);}}}/*//--------------------------SPI读------------------------------------------unsigned char Spi_ByteRead(void){unsigned char i = 0;for (i=0; i<8; i++){DATA_BUF = DA TA_BUF << 1;CLK1 = 1;DATA = 1; //设置为输入状态if (DATA) //读取最高位,保存至最末尾,通过左移位完成整个字节{DA TA_BUF |= BYTE_BIT0;}else{DA TA_BUF &= ~BYTE_BIT0;}CLK1 = 0;}return DATA_BUF;}*///----------------------------------SPI写----------------------------------------- void Spi_ByteWrite(unsigned char send){unsigned char i;DATA_BUF = send;CLK1 = 0;for (i=0; i<8; i++){if (DATA7) //总是发送最高位{DA TA = 1;}else{DA TA = 0;}CLK1 = 1;DATA_BUF = DA TA_BUF << 1;CLK1 = 0;}}//-----------------------------配置2401-------------------------------------------- void Config2401(void){uint i;uchar variable1;PWR_UP=1; //上电CE=0;CS=1; //使RF2401进入配置方式Delay_ms(3); //从上电到进入配置模式需要3ms的延时(最少)for(i=0;i<18;i++) //输入3个测试字节15个配置字节共18Byte{variable1=nRF2401_Conf[i];Spi_ByteWrite(variable1);}CS=0; //Disable CS -----standby modeDATA=0;Delay_us(100);}//--------------------------------设置为发送模式----------------------------void SetTxMode(void){//-------------------------------设置为配置模式---------------------------------- PWR_UP=1; //上电CE=0;CS=1; //进入配置模式Delay_us(100);DATA=0; //配置寄存器0字节RXEN 设置为0: 发送模式CLK1=1;CLK1=0;//----------------------------设置为Activemodes(TX)------------------------------ CS=0;CE=1; //set standby modeDelay_us(100);}//--------------------------------nRF 数据发送函数-------------------------------- void nRF2401_TxPacket(){int i;uchar variable2;CE=1;for(i=0;i<2;i++) //写入接受地址(按字节对齐){variable2=TxAddress[i];Spi_ByteWrite(variable2);}for(i=0;i<(28);i++) //写入接受地址(按字节对齐){variable2=TxBuf[i];Spi_ByteWrite(variable2);}CE=0; //CE配置低使发送有效Delay_us(100); //时钟信号高电平有效}//------------------------------------主函数--------------------------------------- main(){Config2401();while(1){nRF2401_TxPacket();SetTxMode();}}。
单片机驱动标准PC机键盘的C51程序
单片机驱动标准PC机键盘的C51程序单片机驱动标准PC 机键盘的C51 程序//#i nclude”reg51.h”#i nclude “intrins.h”#i nclude “ku.h”//按键通码与ascii对照表sbit sda= p1; //键盘数据线unsigned char dat=0,dat1=0,dat2=0; //接收键盘数据变量? 存储通码变量接受连续通码变量unsigned char count=0,num=9,temp[5],shu=0; //中数次数中断控制变量缓冲区数组缓冲区指针unsigned char key=0; //按键最终值void zhongduan() interrupt 0 //外部中断0 用来接受键盘发来的数据{dat>>=1; //接受数据低->高if(sda) dat|=0x80;count++;if(count==num){if(count==9){dat1=dat; //中断9 次后为键盘所按按键的通码(开始位始终为0 在第一次中断时右移中忽略)num=20; //使中断可以继续中断11 次}if(count==20){dat2=dat; //取回第二个通码if(dat1==0xe0 || dat2==0xf0) //第一个通码是0xe0 则证明所按按键为功能键,第二个通码是0xf0证明按键结束{temp[shu]=dat1;temp[shu+1]=dat2; shu+=2; //将所按按键存到缓冲区中ie=0x82; //关闭外部中断并打开内部中断来处理所按按键tr0=1;} else{temp[shu]=dat1;temp[shu+1]=dat2; shu+=2; //如果shift 键被按下则记录与它同时按下的那个键count=0;}if((temp[0]==18 || temp[0]==89) && (temp[2]==18 || temp[2]==89) ) tr0=1; //如果缓冲区中有两个间隔的shift 键则证明需要的铵键结束}}}void getkey() interrupt 1 //内部中断0 用来处理缓冲区里的数据{unsigned char i=0;tr0=0;th0=0;tl0=0;count=0; //中断记数则0if((temp[0]==18 || temp[0]==89) && temp[1]!=0xf0 ) //shift 被按下{for(i=0;itips:感谢大家的阅读,本文由我司收集整编。
nrf24l01的51驱动程序
#endif
//-----------------------nrf24l01.h结束------------------------------
#define EN_AA 0x01 // 自动应答功能设置
#define EN_RXADDR 0x02 // 可用信道设置
#define SETUP_AW 0x03 // 收发地址宽度设置
#define SETUP_RETR 0x04 // 自动重发功能设
//---------------------nrf24l01.h----------------------------
#ifndef NRF24L01_H
#define NRF24L01_H
#include <reg52.h>
//模式选择
//#define RMODE
#define TMODE
#define RF_CH 0x05 // 工作频率设置
#define RF_SETUP 0x06 // 发射速率、功耗功能设置
#define STATUS 0x07 // 状态寄存器
#define OBSERVE_TX 0x08 // 发送监测功能
#define RX_ADDR_P3 0x0D // 频道3接收数据地址
#define RX_ADDR_P4 0x0E // 频道4接收数据地址
#define RX_ADDR_P5 0x0F // 频道5接收数据地址
基于51单片机与nRF24L01无线门禁控制系统设计
基于51单片机与nRF24L01无线门禁控制系统设计1. 本文概述本文旨在探讨基于51单片机与nRF24L01无线门禁控制系统的设计。
随着科技的快速发展和智能化趋势的加强,门禁控制系统作为保障场所安全的重要手段,其设计与实现变得尤为重要。
传统的门禁系统多采用有线连接方式,布线复杂、成本较高且灵活性不足。
本文提出了一种基于51单片机与nRF24L01无线模块的门禁控制系统设计,旨在实现门禁系统的无线化、智能化和便捷化。
本文将首先介绍51单片机和nRF24L01无线模块的基本原理和特点,为后续的设计工作提供理论基础。
随后,将详细阐述系统的硬件设计,包括无线模块的选型、电路设计以及门禁控制器的实现等。
在此基础上,本文将进一步探讨软件设计的关键问题,包括无线通信协议的制定、门禁控制算法的实现以及用户界面的设计等。
通过本文的研究,旨在设计并实现一个稳定可靠、易于扩展的无线门禁控制系统,为各类场所提供高效便捷的门禁管理解决方案。
同时,本文的研究结果将为相关领域的研究人员提供有益的参考和借鉴,推动无线门禁控制技术的进一步发展。
2. 系统设计原理51单片机,作为一种经典的微控制器,其核心是基于Intel的8051架构。
它具备基本的输入输出控制能力,定时器计数器,中断系统以及一定的内存管理功能。
在本系统中,51单片机扮演着中央处理单元(CPU)的角色,负责接收传感器数据,处理输入信号,并根据预设的逻辑控制输出设备,如无线通信模块和门禁机构。
nRF24L01是一款高性能的无线传输模块,基于Nordic Semiconductor的 NRF24L01 芯片。
它工作在4GHz的ISM频段,支持点对点、点对多点的通信模式。
nRF24L01模块具有自动应答和自动重发功能,确保数据传输的可靠性。
在本系统中,nRF24L01用于无线传输门禁控制信号,包括身份验证数据和控制指令。
系统设计将51单片机和nRF24L01无线模块整合,形成一个高效、可靠的无线门禁控制系统。
nRF24l01无线模块 发送端程序for 51单片机
#define Data P0//数据端口
//=============================================================================================
#define MODE 0//MODE=1时为发送代码 为0则是接受代码
#define uchar unsigned char
#define RX_ADR_WIDTH 5
#define TX_ADR_WIDTH 5 // 5 bytes TX(RX) address width
#define TX_PLOAD_WIDTH 1 // 20 bytes TX payload
/******************************************************************/
void WriteCommand(unsigned char c)
{
DelayMs(5);//操作前短暂延时,保证信号稳定
E=0;
RS=0;
RW=0;
/* 写入字符串函数 */
/******************************************************************/
void ShowString (unsigned char line,char *ptr)
char data TimeNum[]=" ";
/******************************************************************/
单片2.4GHz无线收发一体芯片nRF2401及其应用
shockBurst删接收主要使用Mcu接口引脚cE、 DRl、cIJ(1和DArrA来实现。当正确设置射频包输 入载荷的地址和大小后,置CE为高电平可激活 Rx。此后便可在nRF2401监测信息输入200ps,若收 到有效数据包,则给MCu一个中断并置DRl为高 电平,以使Mcu以时钟形式输出有效载荷数据,待 系统收到全部数据后,nRF2401再置DRl为低;此时 如果cE保持高电平,则等待新的数据包。若cE置 低电平,则开始接收新的序列。 3.2 DuoCeiver删的双信道接收模式
2 主要特点和引脚功能
nRF240l的引脚排列如图l(顶视图)所示。它采
用5栅×5姗的24引脚QFN封装。表1所列是其
引脚功能。nRF2401的主要特点如下: ●采用全球开放的2.4G比频段,有125个频
道,可满足多频及跳频需要; ●速率(1Mbps)高于蓝牙,且具有高数据吞吐量;
●外围元件极少,只需一个晶振和一个电阻 可设计射频电路;
图2 nRF240l内部原理及外部组成框图
万方数据
一36一
《国外电子元器件》2004年第6期2004年6月
3 工作原理
nRF2401的内部结构原理及外部组成框图如图 2所示,下面介绍其工作原理。 3.1 ShockBurstlM模式
nRF2401的ShockBurStTM RX/TX模式采用片上 先进先出(FIF0)来进行低数据率的时钟同步和高数 据率的传输,因此极大的降低了功耗。
nrf401实验c51程序
nrf401实验c51程序/*---------------------------------------------------------------------- nrf401实验程序雁塔菜农HotPower@-----------------------------------------------------------------------*/ #i nclude <AT89X52.h>#i nclude <stdio.h>#i nclude <absacc.h>#i nclude <intrins.h>#i nclude <nrf401.h>#i nclude <hotins.h>#define T0_8mS -8000#define T1_8mS -8000#define T2_1_25mS -576 //-1250*0.9216=1.25MS/*---------------------------------------------------------------------- 系统函数-----------------------------------------------------------------------*/ void MainInit(void);//系统初始化void ClrWdt(void);//喂狗void nRFInit(void);void SystemInit(void);//系统初始化void SystemSetup(void);//系统设置void SystemIoInit(void);//系统接口初始化void UserSetup(void);//用户运行环境设置void TimeInit(void);unsigned char crc8r(unsigned char crcbyte);unsigned int crc16r(unsigned int crcword, unsigned int crc);unsigned int GetTXBuffWord(unsigned char ledpos);void SetTXBuffWord(unsigned char ledpos, unsigned int val);unsigned int GetRXBuffWord(unsigned char ledpos);void SetRXBuffWord(unsigned char ledpos, unsigned int val);SystemData SystemBuffers;//申请系统数据结构SioData SioBuffers;/*-----------------------------------------主程序初始化-------------------------------------------*/void MainInit(void)//系统初始化{SystemIoInit();//系统接口初始化ClrWdt();//清除看门狗计数器if (SystemBuffers.RamTest != 0x55aa) {//内存测试SystemInit();//系统上电初始化}SystemSetup();//系统运行环境设置UserSetup();//用户运行环境设置}void SystemInit(void)//系统初始化{SystemBuffers.RamTest = 0x55aa;//内存初始化}void SystemSetup(void)//系统设置{AUXR = 0x01;//关闭EMInRFInit();TimeInit();IP = 0x10;//中断优先级EX1>ET2>ET0>EX0>ESIE = 0xb4;//开中断EA,ET2,ET1,EX1,ET0}void UserSetup(void)//用户运行环境设置{}void SystemIoInit(void){IE = 0x00;//关闭中断P0 = 0xff;//P0口初始化P1 = 0xff;//P1口初始化P2 = 0xff;//P2口初始化P3 = 0xff;//P3口初始化}void TimeInit(){TMOD = 0x21;//定时器0,1为方式1(十六位定时器)TCON = 0x55;//启动定时器TR1EQUTR0EQU1,IT1EQUIT0EQU1定时器0定时参数设置----------------------------------*/TL0 = 0;TH0 = 0;TR0 = 1;//启动定时器0/*----------------------------------定时器0定时参数设置----------------------------------*/TL1 = SIO_BPS;TH1 = SIO_BPS;PCON = 0x00;TR1 = 1;//启动定时器1/*----------------------------------定时器2定时参数设置----------------------------------*/TIMEER2 = T2_1_25mS;RCAP = T2_1_25mS;TR2 = 1;//启动定时器2}void nRFInit(void){nRFCS = 0;//433.92MHz//1//434.33MHznRFTXEN = 0;//接收nRFPWR = 1;//上电SioBuffers.TXMAXCount = 0;SioBuffers.TXCount = 0;// SioBuffers.RXCount = 0;SCON = 0x50; /* SCON: mode 2, 9-bit UART, enable rcvr */ SioBuffers.RXCount = 16;}/*------------------------------------外部INT0中断服务程序------------------------------------*/void int0proc() interrupt IE0_VECTOR// using 1{}/*------------------------------------定时器T0中断服务程序void t0proc() interrupt TF0_VECTOR// using 1{}/*------------------------------------外部INT1中断服务程序------------------------------------*/void int1proc() interrupt IE1_VECTOR using 1{}/*------------------------------------定时器T1中断服务程序------------------------------------*/void t1proc() interrupt TF1_VECTOR// using 1{}/*------------------------------------串口SIO中断服务程序------------------------------------*/void sioproc() interrupt SIO_VECTOR// using 1{unsigned char i;unsigned int crc;if (RI) {//接收中断RI = 0;if (!nRFTXEN && SioBuffers.RXCount) {//每次接收20个数据 i = SBUF;SioBuffers.RXCount --;SioBuffers.RXBuffers[19 - SioBuffers.RXCount] = i; switch(SioBuffers.RXCount) {case 19:if (i != 0x55) SioBuffers.RXCount = 20;break;case 18:if (i != 0xaa) SioBuffers.RXCount = 20;break;case 0:crc = 0;for (i = 1; i <= 8; i ++) {crc = crc16r(GetRXBuffWord(i + i), crc);}if (crc != GetRXBuffWord(18))SioBuffers.RXCount = 20;else {nRFTXEN = 1;//发送for (i = 0; i < 20; i ++) {SioBuffers.TXBuffers[i] = SioBuffers.RXBuffers[i]; }SioBuffers.TXMAXCount = TX_MAXCount;SioBuffers.TXCount = TX_Count + 32;TI = 1;//接收结束立即转为发送}break;}}}if (TI) {//发送中断TI = 0;if (nRFTXEN && SioBuffers.TXCount) {SioBuffers.TXCount --;if (SioBuffers.TXCount > 19) {SBUF = 0x00;// SBUF = 0xff;}else {SBUF = SioBuffers.TXBuffers[19 - SioBuffers.TXCount]; }if (SioBuffers.TXCount == 0) {if (SioBuffers.TXMAXCount) {SioBuffers.TXMAXCount --;SioBuffers.TXCount = TX_Count;}else {nRFTXEN = 0;//发送结束立即转为接收SioBuffers.RXCount = 20;}}}}}/*------------------------------------定时器T2中断服务程序(1.25mS)------------------------------------*/void t2proc() interrupt TF2_VECTOR// using 2{//unsigned char i;//unsigned int crc;TF2 = 0;if (PCON & GF0) {//中断是从主循环内跳入的才能喂狗ClrWdt();//清除看门狗计数器PCON &= ~GF0;//清除标志}SystemBuffers.T2Count ++;// if (SystemBuffers.T2Count >= 80) {//100mS到if (SystemBuffers.T2Count >= 400) {//500mS到SystemBuffers.T2Count = 0;//if (((SystemBuffers.T2Count & 3) == 0) && (SioBuffers.TXCount == 0)) {//10mS //if (SioBuffers.TXCount == 0) {//10mS/*if (!ES && (SioBuffers.TXCount == 0)) {//10mSSioBuffers.TXCount = 18;crc =GetTXBuffWord(2);crc = crc16r(crc);SetTXBuffWord(4, crc);nRFTXEN = 1;//发送TI = 1;ES = 1;}*/// SioBuffers.TXCount = 8;// nRFTXEN = 1;//发送// SBUF = SioBuffers.TXBuffers[0];// ES = 1;}}void ClrWdt(void)//喂狗{WDTRST = 0x1e;//89s52内狗WDTRST = 0xe1;//89s52内狗}unsigned char crc8r(unsigned char crcbyte){unsigned char i,crc;crc = 0;for(i = 0; i < 8; i++) {if(((crc ^ crcbyte) & 0x01) == 0) crc >>= 1;else{crc ^= 0x18;//0x18;//CRC=X8+X5+X4+1crc >>= 1;crc |= 0x80;}crcbyte >>= 1;}return crc;}unsigned int crc16r(unsigned int crcword, unsigned int crc) {unsigned char i;for(i = 0; i < 16; i++){if(((crc ^ crcword ) & 0x0001) == 0) crc >>= 1;else{crc ^= 0x810;//0x0810;//CRC=X16+X12+X5+1crc >>= 1;crc |= 0x8000;}crcword >>= 1;}return crc;}unsigned int GetTXBuffWord(unsigned char ledpos){unsigned char val1, val2;unsigned int val;val1 = SioBuffers.TXBuffers[ledpos];val2 = SioBuffers.TXBuffers[ledpos + 1];val = (val1 << 8) + val2;return val;}void SetTXBuffWord(unsigned char ledpos, unsigned int val) {SioBuffers.TXBuffers[ledpos] = (val >> 8);SioBuffers.TXBuffers[ledpos + 1] = val & 0xff;}unsigned int GetRXBuffWord(unsigned char ledpos){unsigned char val1, val2;unsigned int val;val1 = SioBuffers.RXBuffers[ledpos];val2 = SioBuffers.RXBuffers[ledpos + 1];val = (val1 << 8) + val2;return val;}void SetRXBuffWord(unsigned char ledpos, unsigned int val) {SioBuffers.RXBuffers[ledpos] = (val >> 8);SioBuffers.RXBuffers[ledpos + 1] = val & 0xff;}。
NRF24L01无线串口开发板程序详解
1.源程序开发环境建立1.1程序编译软件编译软件用keil C51,打开安装文件,一路点击下一步即可完成。
1.2程序下载软件使用STC ISP下载软件。
2.源程序文件整体结构工程中,只有一个main.c文件,所有程序都写在这个文件里面。
Reg51.h是包含的头文件。
是不是非常简单!3.源程序执行流程无线数据处理程序:串口数据处理程序:4.串口配置函数void serial_open(void){SCON = 0X50;AUXR |= 0X04;TL2 = 0Xc0; // 9600TH2 = 0Xfd;AUXR|=0X10;}此串口配置函数,利用单片机内部的定时器2作为波特率发生器。
共用到4个寄存器:SCON AUXR TL2 TH2SM0和SM1的位决定串口工作的4种方式:程序中,SCON=0X50,即SM0=0 SM1=1,即串口工作在“方式1”;REN=1,允许串口接收数据。
TL2和TH2是定时器2的高位和低位寄存器。
程序中,首先AUXR|=0X40,最后AUXR|=0X10。
即首先把T2x12置1,然后把T2R置1。
即首先把定时器2设置为1T模式,然后把定时器打开。
5.串口发送数据函数void senddata(uchar data_buf){SBUF = data_buf;while(!TI);TI = 0;}用到了寄存器SBUF和寄存器SCON中的TI位。
SBUF寄存器是串口收发数据缓存寄存器,放到这个寄存器中的数据,会通过串口发送出去,接收到的串口数据,也会放到这个寄存器中。
也就是串口接收和发送都是使用这个寄存器。
程序中,SBUF=data_buf,就是把data_buf给了SBUF,单片机自动把SBUF里面的数据发送到串口。
TI是串口发送数据完成标志位,当串口发送完一个数据,此位置1,置位后,需要通过软件清0。
所以通过while(!TI),来检测TI位,达到检测串口是否发送完数据的目的。
NRF2401详细注释编程程序
厂函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
厂功能:数据读取后放如rx_buf接收缓冲区中
unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)
uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)
{
uint status,uchar_ctr;
CSN = 0;// Set CSN low, init SPI tranaction
status = SPI_RW(reg); // Select register to write to and read status uchar
SPI_RW_Reg(WRITE_REG +CONFIG, OxOe); //IRQ收发完成中断响应.16位CRC,主发送
CE=1;〃萱高CE,激发数据发送
inerDelay_us(10);
*****扌***********4(4(****4(******京*******************/***
{
unsigned char revale=O;
sta=SPI_Read(STATUS); //读取状态寄存其来判断数据接收状况
if(RX_DR)//判断是否接收到数据
{
CE = O; //SPI使能
SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO buffer
/*函数:uint SPI_Write_Buf(uchar reg, uchar *pBufzuchar uchars)
NRF24L01无线模块C语言程序
NRF24L01无线模块C语言程序24MHz晶振#include#include#include#include#include#include#define U8 unsigned char#define U16 unsigned int#define TX_ADDR_WITDH 5 //发送地址宽度设置为5个字节#define RX_ADDR_WITDH 5 //接收地址宽度设置为5个字节#define TX_DATA_WITDH 1//发送数据宽度1个字节#define RX_DATA_WITDH 1//接收数据宽度1个字节#define R_REGISTER 0x00//读取配置寄存器#define W_REGISTER 0x20//写配置寄存器#define R_RX_PAYLOAD 0x61//读取RX有效数据#define W_TX_PAYLOAD 0xa0//写TX有效数据#define FLUSH_TX 0xe1//清除TXFIFO寄存器#define FLUSH_RX 0xe2//清除RXFIFO寄存器#define REUSE_TX_PL 0xe3//重新使用上一包有效数据#define NOP 0xff//空操作#define CONFIG 0x00//配置寄存器#define EN_AA 0x01//使能自动应答#define EN_RXADDR 0x02//接收通道使能0-5个通道#define SETUP_AW 0x03//设置数据通道地址宽度3-5 #define SETUP_RETR 0x04//建立自动重发#define RF_CH 0x05//射频通道设置#define RF_SETUP 0x06//射频寄存器#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//P0通道数据宽度设置#define RX_PW_P1 0x12//P1通道数据宽度设置#define RX_PW_P2 0x13//P2通道数据宽度设置#define RX_PW_P3 0x14//P3通道数据宽度设置#define RX_PW_P4 0x15//P4通道数据宽度设置#define RX_PW_P5 0x16//P5通道数据宽度设置#define FIFO_STATUS 0x17//FIFO状态寄存器//NRF24L01U8 NRFACK();U8 NRFSPI(U8 date);U8 NRFReadReg(U8 RegAddr);U8 NRFWriteReg(U8 RegAddr,U8 date);U8 NRFReadRxDate(U8 RegAddr,U8 *RxDate,U8 DateLen);U8 NRFWriteTxDate(U8 RegAddr,U8 *TxDate,U8 DateLen);U8 NRFRevDate(U8 *RevDate);void NRFSetTxMode(U8 *TxDate);void NRF24L01Int();void NRFSetRXMode();U8 CheckACK();void Delay(U16 t);U8 bdata sta;//mainvoid Delay_10ms(U16 del);bit CE=P1^4; //RX/TX模式选择端sbit IRQ=P1^1; //可屏蔽中断端sbit CSN=P1^6; //SPI片选端//就是SSsbit MOSI=P1^0; //SPI主机输出从机输入端1sbit MISO=P1^2; //SPI主机输入从机输出端sbit SCLK=P1^3; //SPI时钟端U8 code TxAddr[]={0x34,0x43,0x10,0x10,0x01};//发送地址U8 bdata sta; //状态标志sbit RX_DR=sta^6;sbit TX_DS=sta^5;sbit MAX_RT=sta^4;void Delay(U16 t){U16 x,y;for(x=t;x>0;x--)for(y=110;y>0;y--);}U8 NRFSPI(U8 date){U8 i;for(i=0;i<8;i++) // 循环8次{if(date&0x80)MOSI=1;elseMOSI=0; // byte最高位输出到MOSIdate<<=1; // 低一位移位到最高位SCLK=1;if(MISO) // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据date|=0x01; // 读MISO到byte最低位 SCLK=0; // SCK置低}return(date); // 返回读出的一字节}void NRF24L01Int(){Delay(2);//让系统什么都不干CE=0; //待机模式1CSN=1;SCLK=0;IRQ=1;}U8 NRFReadReg(U8 RegAddr){U8 BackDate;CSN=0;//启动时序NRFSPI(RegAddr);//写寄存器地址BackDate=NRFSPI(0x00);//写入读寄存器指令CSN=1;return(BackDate); //返回状态}U8 NRFWriteReg(U8 RegAddr,U8 date){U8 BackDate;CSN=0;//启动时序BackDate=NRFSPI(RegAddr);//写入地址NRFSPI(date);//写入值CSN=1;return(BackDate);}U8 NRFReadRxDate(U8 RegAddr,U8 *RxDate,U8 DateLen){ //寄存器地址//读取数据存放变量//读取数据长度//用于接收 U8 BackDate,i;CSN=0;//启动时序BackDate=NRFSPI(RegAddr);//写入要读取的寄存器地址for(i=0;i{RxDate[i]=NRFSPI(0);}CSN=1;return(BackDate);}U8 NRFWriteTxDate(U8 RegAddr,U8 *TxDate,U8 DateLen){ //寄存器地址//写入数据存放变量//读取数据长度//用于发送 U8 BackDate,i;CSN=0;BackDate=NRFSPI(RegAddr);//写入要写入寄存器的地址for(i=0;i{NRFSPI(*TxDate++);}CSN=1;return(BackDate);}void NRFSetTxMode(U8 *TxDate){//发送模式CE=0;NRFWriteTxDate(W_REGISTER+TX_ADDR,TxAddr,TX_ADDR_WITDH);//写寄存器指令+接收地址使能指令+接收地址+地址宽度NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH);//为了应答接收设备,接收通道0地址和发送地址相同NRFWriteTxDate(W_TX_PAYLOAD,TxDate,TX_DATA_WITDH);//写入数据NRFWriteReg(W_REGISTER+EN_AA,0x01); // 使能接收通道0自动应答NRFWriteReg(W_REGISTER+EN_RXADDR,0x01); // 使能接收通道0NRFWriteReg(W_REGISTER+SETUP_RETR,0x0a); // 自动重发延时等待250us+86us,自动重发10次NRFWriteReg(W_REGISTER+RF_CH,0x40); // 选择射频通道0x40NRFWriteReg(W_REGISTER+RF_SETUP,0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益NRFWriteReg(W_REGISTER+CONFIG,0x0e); // CRC使能,16位CRC 校验,上电CE=1;Delay(5);//保持10us秒以上}//主要接收模式void NRFSetRXMode(){CE=0;NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH); // 接收设备接收通道0使用和发送设备相同的发送地址NRFWriteReg(W_REGISTER+EN_AA,0x01);// 使能接收通道0自动应答NRFWriteReg(W_REGISTER+EN_RXADDR,0x01); // 使能接收通道0NRFWriteReg(W_REGISTER+RF_CH,0x40);// 选择射频通道0x40NRFWriteReg(W_REGISTER+RX_PW_P0,TX_DATA_WITDH); // 接收通道0选择和发送通道相同有效数据宽度NRFWriteReg(W_REGISTER+RF_SETUP,0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益*/NRFWriteReg(W_REGISTER+CONFIG,0x0f); / / CRC使能,16位CRC校验,上电,接收模式CE = 1;Delay(5);//保持10us秒以上}U8 CheckACK(){ //用于发射sta=NRFReadReg(R_REGISTER+STATUS);// 返回状态寄存器if(TX_DS||MAX_RT) //发送完毕中断{NRFWriteReg(W_REGISTER+STATUS,0xff); // 清除TX_DS或MAX_RT 中断标志CSN=0;NRFSPI(FLUSH_TX);//用于清空FIFO !!关键!!不然会出现意想不到的后果!!!大家记住!!CSN=1;return(0);}elsereturn(1);}//用于接收模式U8 NRFRevDate(U8 *RevDate){U8 RevFlags=0;sta=NRFReadReg(R_REGISTER+STATUS);//发送数据后读取状态寄存器 if(RX_DR) // 判断是否接收到数据{CE=0; //SPI使能NRFReadRxDate(R_RX_PAYLOAD,RevDate,RX_DATA_WITDH);// 从RXFIFO读取数据RevFlags=1; //读取数据完成标志}NRFWriteReg(W_REGISTER+STATUS,0xff); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标return(RevFlags);}void Delay_10ms(U16 del){U16 i,j;for(i=0; i<del; i++)for(j=0; j<1827; j++) //这个是通过软件仿真得出的数;}// 做发射main(){U8 TxDate[1]={0};NRF24L01Int();Delay(6000);while(1){if(KEY==0){if(KEY==0){Delay_10ms(2);TxDate[0]=0x08;//发射按键标识值NRFSetTxMode(TxDate);while(CheckACK());TxDate[0]=0;}}}}//// 做接收:一直处于接受模式查询所得到的值是不是0x08 main(){U8 x;U8 RxBuf[1]={0};NRF24L01Int();Delay(6000);while(1){NRFSetRXMode();NRFRevDate(RxBuf);x=RxBuf[0];if(x==0x08)//0x08为发射部分所发送的按键标识{////加入所要执行的功能函数//当然了这里用到单片机io口的时候需要在之前定义//还有就是发送程序中的KEY也需要之前定义好 RxBuf[0]=0;}}}。
51单片机驱动超声波测距模块C51程序
51单片机驱动超声波测距模块C51程序51单片机驱动超声波测距模块C51程序#include;#define uchar unsigned char#define uint unsigned int#define ulong unsigned long//******************* 函数声明**************************void init_T otal(); //总初始化void init_T0(); //初始化定时器T0void init_T1(); //初始化定时器T1void init_inter0();//初始化外部中断1void send_T();void delay(uint z);//延时一段时间void delay_300us();//延时300usvoid delay_100us();//延时100us//*********************************************** *********sbit lcdrs=P1^7;sbit lcdrw=P3^1;sbit lcden=P1^5;//1602液晶控制端sbit send=P1^0;//sbit BEEP=P2^5;sbit wei=P2^6;sbit duan=P2^7;volatile uchar Count_TH ,Count_TL;//分别读计数器T1的高位TH1,低位TL1uchar t0,flag;uint time;uchar code table1[]=" distance "; uchar code table2[]=" ";//初始化显示void write_com(uchar com)//1602写指令函数{lcdrs=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;void write_data(uchar datb)//1602写数据函数{ lcdrs=1;P0=datb;delay(1);lcden=1;delay(1);lcden=0;}void distance(uchar addr,uint datb){uchar bai,shi,ge ;bai=datb/100;shi=datb%100/10;ge=datb%10;write_com(0x80+0x40+addr);write_data(0x30+bai);write_data(0x30+shi);write_data(0x30+ge);}/************************************************ *************************************** 名称:void init_T otal()* 功能:总初始化* 入口参数:NULL* 全局变量:NULL* 返回值:NULL**************************************************************************************/void init_T otal(){init_T0(); //初始化定时器T0为工作方式2 init_T1(); //初始化定时器T1为工作方式1 init_inter0();//初始化外部中断1EA=1; //开总中断}/*************************************************************************************** 名称:void init_T0()* 功能:初始化定时器T0为工作方式2* 入口参数:NULL* 全局变量:NULL* 返回值:NULL**************************************************************************************/void init_T0(){TMOD=0X12;TH0=0XE7;TL0=0XE7;EA=0;ET0=1;TR0=1;}/************************************************ *************************************** 名称:void init_T1()* 功能:初始化定时器T1为工作方式1* 入口参数:NULL* 全局变量:NULL* 返回值:NULL************************************************* *************************************/void init_T1(){TMOD=0X12;TH1=0;TL1=0;EA=0;ET1=1;TR1=1;}/************************************************ *************************************** 名称:void init_inter1()* 功能:初始化外部中断1为低电平触发方式* 入口参数:NULL* 全局变量:NULL* 返回值:NULL************************************************* *************************************/void init_inter0(){IT0=0; //低电平触发EA=0;EX0=0; //关外部中断1}/************************************************ *************************************** 名称:void inter_T0() interrupt 1* 功能:定时器T0中断函数产生40KHZ的方波* 入口参数:NULL* 全局变量:NULL* 返回值:NULL************************************************* *************************************/void inter_T0() interrupt 1{send=~send;}/************************************************ *************************************** 名称:void inter_T1() interrupt 3* 功能:定时器T1中断函数* 入口参数:NULL* 全局变量:NULL* 返回值:NULL************************************************* *************************************/void inter_T1() interrupt 3{TR1=0;EX0=0; //关外部中断0TH1=0;TL1=0;flag=2;}/************************************************ *************************************** 名称:void inter1() interrupt 2* 功能:外部中断1函数* 入口参数:NULL* 全局变量:Count_TH,Count_TL* 返回值:NULL************************************************* *************************************/void inter0() interrupt 0{TR1=0;EX0=0;flag=1;}/************************************************ *************************************** 名称:void send_T()* 功能:发送10个超声波脉冲* 入口参数:NULL* 全局变量:Count* 返回值:NULL************************************************* *************************************/void send_T(){delay_100us();//发送100us的方波TR0=0;//关定时器T0}/************************************************ *************************************** 名称:void delay(uint z)* 功能:延时一段时间* 入口参数:z* 全局变量:NULL* 返回值:NULL************************************************* *************************************/void delay(uint z){uint x,y;for(x=z;x>;0;x--)for(y=1000;y>;0;y--);}/************************************************ *************************************** 名称:void delay_300us()* 功能:延时300us* 入口参数:NULL* 全局变量:NULL* 返回值:NULL************************************************* *************************************/void delay_300us(){uint x;for(x=75;x>;0;x--);}/************************************************ *************************************** 名称:void delay_100us()* 功能:延时100us* 入口参数:NULL* 全局变量:NULL* 返回值:NULL************************************************* *************************************/void delay_100us(){uint x;for(x=24;x>;0;x--);}//*********************************************** ****************************************void main(){uint t,s;init_T otal();//总初始化while(1){TR1=1;//启动定时器1TR0=1;//启动定时器0send_T(); //发送100us超声波脉冲delay_300us();//延时300us跳过盲区EX1=1; //开外部中断1while(!flag); //等待回波或定时器T1溢出if(flag==1) //回波{Count_TH=TH1;//读计数器T1的高位TH1 Count_TL=TL1;//读计数器T1的低位TL1 t=Count_TH*256+Count_TL;s=(33140*t)/400000;distance(4,s);//液晶1602显示距离 }/* else //定时器T1溢出{Count_TH=0XFE;Count_TL=0X7F;// P2=Count_TH;P2=Count_TL;}*/delay(150);flag=0;//标志位清0TH1=0; //T1清0重新计时TL1=0;}}。
TFT2.4 C51驱动程序
TFT控制器TL1763初始化及显示驱动程序2011,2,27#include "lcd.h"#include "asc_zimo.h"#include "Hz_zimo.h"#define LT1763#define DATA_12864U16 PenColor;U16 BackColor;//==================== 微秒延时子程序========================== void DelayUs(U16 us){while(us--);}//=================== 毫秒延时子程序=========================== void DelayMs( U16 ms){while(ms--)DelayUs(149);}//=================================#ifdef DATA_12864void LCD_WrCmd(U16 cmd)//时序见手册{LCD_nCS=0;LCD_RS=0;LCD_DAT=(cmd>>8); //write high byteLCD_nWR=0;LCD_nWR=1;LCD_DAT=(cmd&0xff); //write low byteLCD_nWR=0;LCD_nWR=1;LCD_nCS=1;}//================================= void LCD_WrDat(U16 dat){LCD_nCS=0;LCD_RS=1;LCD_DAT=(dat>>8); //write high byteLCD_nWR=0;LCD_nWR=1;LCD_DAT=(dat&0xff); //write low byteLCD_nWR=0;LCD_nWR=1;LCD_nCS=1;}U16 LCD_RdDat(void){U16 buf;buf = XBYTE[0x1C00];/*LCD_nCS_0;LCD_RS_1;LCD_nRD_0;buf=LCD_Dat_Rd;buf=buf & 0xff00; //read high byteLCD_nRD_1;LCD_nRD_0;buf=(LCD_Dat_Rd>>8)|buf;//read low byteLCD_nRD_1;LCD_nCS_1;return buf;*/}#endif//=================================void LCD_WrCmdDat(U16 addr,U16 dat){LCD_WrCmd(addr);LCD_WrDat(dat);}#ifdef ILI9325void LCD_Init(void){LCD_BLEN_0;LCD_nRST_0; //低电平复位DelayMs(10);LCD_nRST_1;//************* Start Initial Sequence **********//LCD_WrCmdDat(0x00E3, 0x3008);// Set internal timingLCD_WrCmdDat(0x00E7, 0x0012); // Set internal timingLCD_WrCmdDat(0x00EF, 0x1231); // Set internal timingLCD_WrCmdDat(0x0001, 0x0100); // set SS and SM bitLCD_WrCmdDat(0x0002, 0x0700); // set 1 line inversionLCD_WrCmdDat(0x0003, 0x1030); // set GRAM write direction and BGR=1.LCD_WrCmdDat(0x0004, 0x0000); // Resize registerLCD_WrCmdDat(0x0008, 0x0207); // set the back porch and front porchLCD_WrCmdDat(0x0009, 0x0700); //00,00//set non-display area refreshcycle ISC[3:0]LCD_WrCmdDat(0x000A, 0x0000); // FMARK functionLCD_WrCmdDat(0x000C, 0x0000); // RGB interface settingLCD_WrCmdDat(0x000D, 0x0000); // Frame marker PositionLCD_WrCmdDat(0x000F, 0x0000); // RGB interface polarity//*************Power On sequence ****************//LCD_WrCmdDat(0x0010, 0x00f0); //00,00//SAP,BT[3:0],AP,DSTB,SLP, STB LCD_WrCmdDat(0x0011, 0x0007); // DC1[2:0], DC0[2:0], VC[2:0]LCD_WrCmdDat(0x0012, 0x0096); //00,00 // VREG1OUT voltageLCD_WrCmdDat(0x0013, 0x0000); // VDV[4:0] for VCOM amplitudeDelayMs(200); // Dis-charge capacitor power voltageLCD_WrCmdDat(0x0010, 0x1490); // SAP, BT[3:0], AP, DSTB, SLP, STB LCD_WrCmdDat(0x0011, 0x0227); // Set DC1[2:0], DC0[2:0], VC[2:0]DelayMs(50); // Delay 50msLCD_WrCmdDat(0x0012, 0x001D); // External reference voltage= Vci;DelayMs(50); // Delay 50msLCD_WrCmdDat(0x0013, 0x1A00); // Set VDV[4:0] for VCOM amplitudeLCD_WrCmdDat(0x0029, 0x0033); //00,0b // SetVCM[5:0] for VCOMH LCD_WrCmdDat(0x002B, 0x000e); //00,00 // Set Frame RateDelayMs(50); // Delay 50msLCD_WrCmdDat(0x0020, 0x0000); // GRAM horizontal AddressLCD_WrCmdDat(0x0021, 0x0000); // GRAM Vertical Address// ----------- Adjust the Gamma Curve ----------//LCD_WrCmdDat(0x0030, 0x0007);LCD_WrCmdDat(0x0031, 0x0206);LCD_WrCmdDat(0x0032, 0x0506);LCD_WrCmdDat(0x0035, 0x0704);LCD_WrCmdDat(0x0036, 0x1203);LCD_WrCmdDat(0x0037, 0x0007);LCD_WrCmdDat(0x0038, 0x0000);LCD_WrCmdDat(0x0039, 0x0706);LCD_WrCmdDat(0x003C, 0x0701);LCD_WrCmdDat(0x003D, 0x000F);//------------------ Set GRAM area ---------------//LCD_WrCmdDat(0x0050, 0x0000); // Horizontal GRAM Start Address LCD_WrCmdDat(0x0051, 0x00EF); // Horizontal GRAM End Address LCD_WrCmdDat(0x0052, 0x0000); // V ertical GRAM Start AddressLCD_WrCmdDat(0x0053, 0x013F); // Vertical GRAM Start AddressLCD_WrCmdDat(0x0060, 0xA700); // Gate Scan LineLCD_WrCmdDat(0x0061, 0x0001); // NDL,VLE, REVLCD_WrCmdDat(0x006A, 0x0000); // set scrolling line//-------------- Panel Control -------------------// */LCD_WrCmdDat(0x0090, 0x0010);LCD_WrCmdDat(0x0092, 0x0600);LCD_WrCmdDat(0x0093, 0x0003);LCD_WrCmdDat(0x0095, 0x0110);LCD_WrCmdDat(0x0097, 0x0000);LCD_WrCmdDat(0x0098, 0x0000);LCD_WrCmdDat(0x0007, 0x0133); // 262K color and display ONDelayMs(100);LCD_BLEN_1;PenColor=YELLOW;BackColor=RED;}#endif#ifdef LT1763void LCD_Init(void){LCD_BLEN_1;LCD_nWR_1;//ALE=1;LCD_nRST_0; //低电平复位DelayMs(10);LCD_nRST_1;//================ Start Initial Sequence ==============// LCD_WrCmdDat(0x0011, 0x0001); //LCD_WrCmdDat(0x0013, 0x1334); //LCD_WrCmdDat(0x0010, 0x0530); //LCD_WrCmdDat(0x0012, 0x101D); //DelayMs(100);LCD_WrCmdDat(0x0013, 0x3334); //LCD_WrCmdDat(0x0011, 0x0111); //LCD_WrCmdDat(0x0010, 0x1530); //DelayMs(100);//initial settingLCD_WrCmdDat(0x0001,0x0100);LCD_WrCmdDat(0x0002,0x0700);LCD_WrCmdDat(0x0003,0x1030);LCD_WrCmdDat(0x0004,0x0141);LCD_WrCmdDat(0x0007,0x0005);LCD_WrCmdDat(0x0008,0x0202);LCD_WrCmdDat(0x000B,0x0000);LCD_WrCmdDat(0x000C,0x0000);LCD_WrCmdDat(0x000E,0x0015);LCD_WrCmdDat(0x00A1,0x1000);LCD_WrCmdDat(0x00A4,0x7300);LCD_WrCmdDat(0x0030,0x0202);LCD_WrCmdDat(0x0031,0x0000);LCD_WrCmdDat(0x0032,0x0404);LCD_WrCmdDat(0x0033,0x0203);LCD_WrCmdDat(0x0034,0x0207);LCD_WrCmdDat(0x0035,0x0202);LCD_WrCmdDat(0x0036,0x0707);LCD_WrCmdDat(0x0037,0x0002);LCD_WrCmdDat(0x0038,0x0F00);LCD_WrCmdDat(0x0039,0x0002);LCD_WrCmdDat(0x0040,0x0000);LCD_WrCmdDat(0x0041,0x0000);LCD_WrCmdDat(0x0042,0x0140);LCD_WrCmdDat(0x0043,0x0000);LCD_WrCmdDat(0x0044,0x0000);LCD_WrCmdDat(0x0045,0x0000);LCD_WrCmdDat(0x0046,0xEF00);LCD_WrCmdDat(0x0047,0x013F);LCD_WrCmdDat(0x0048,0x0000);DelayMs(100);//display on settingLCD_WrCmdDat(0x0007,0x0025);LCD_WrCmdDat(0x0007,0x0027);DelayMs(100);LCD_WrCmdDat(0x0007,0x0037);LCD_WrCmdDat(0x0020,0x0000);LCD_WrCmdDat(0x0021,0x0000);DelayMs(100);LCD_BLEN_0;PenColor=YELLOW;BackColor=RED;}#endif/*========================================================== * Function : LCD_SetPoit* Description : 设置lcd memory point* Input Para : U8 StartX, U8 StartY* Output Para : void* Return Value: void===========================================================*/ void LCD_SetGramPoit(U16 x,U16 y){LCD_WrCmdDat(0x0020,x);LCD_WrCmdDat(0x0021,y);LCD_WrCmd(0x0022); //设置地址后重新启动写RAM命令}/*========================================================== * Function : lcd_set_write_area* Description : 设置lcd memory write的区域* Input Para : U8 StartX, U8 StartY,U8 EndX, U8 EndY* Output Para : void* Return Value: void======================================================*/#ifdef ILI9325void LCD_SetWindows(U16 HSA, U16 VSA,U16 HEA, U16 VEA){LCD_WrCmdDat(0x0050,HSA);LCD_WrCmdDat(0x0051,HEA);LCD_WrCmdDat(0x0052,VSA);LCD_WrCmdDat(0x0053,VEA);//LCD_SetGramPoit(HSA,VSA); //根据扫描方式不同而不同}#endif#ifdef LT1763void LCD_SetWindows(U16 HSA, U16 VSA,U16 HEA, U16 VEA){LCD_WrCmdDat(0x0046,(HEA<<8)|HSA); //R46窗口水平起始结束地址,高八位为结束地址LCD_WrCmdDat(0x0048,VSA); //R48 窗口垂直起始地址LCD_WrCmdDat(0x0047,VEA); // R47 窗口垂直结束地址//LCD_SetGramPoit(HSA,VSA); //根据扫描方式不同而不同}#endif* 名称: DispOneColor* 功能: 使任意矩形显示某种颜色* 参数: 颜色值:Color* 返回值: 无********************************************************************/ void DispOneColor(U16 X,U16 Y,U16 W,U16 H,U16 Color){U16 i,j;LCD_SetWindows(X,Y,X+W-1,Y+H-1);LCD_SetGramPoit(X,Y); //根据扫描方式不同而不同for(i=0;i<H;i++){for(j=0;j<W;j++){LCD_WrDat(Color);}}}void LCD_Clear(void){DispOneColor(LCD_Sx, LCD_Sy, LCD_W, LCD_H,BackColor);}/*========================================================== * Function : lcd_display_full_screen_color* Description : 将全屏刷为某一颜色* Input Para : U16 val* Output Para : void* Return Value: void===========================================================*/ void Display_full_screen_color(U16 color){U16 X, Y;LCD_SetWindows(LCD_Sx, LCD_Sy, LCD_Ex, LCD_Ey);LCD_SetGramPoit(LCD_Sx,LCD_Sy); //根据扫描方式不同而不同for(X = 0; X < LCD_W; X++){ for(Y = 0; Y < LCD_H; Y++){LCD_WrDat(color);}}return;}* 名称: DrawSingleAscii* 功能: 在指定的位置显示单个字符* 参数: 坐标:x* 坐标:y* 字符的颜色:LineColor* 字符背景颜色:FillColor :* 返回值: 无*******************************************************************/ void DrawSingleAscii(U16 x, U16 y, U8 *pHz, U16 LineColor,U16 FillColor, U8 Mod){U16 j=0,i=0,k=0;U8 str;U16 len;//---------------------------查找该字是否已在字库中len=sizeof(AsciiLib)/sizeof(AsciiLib[0]);for(j=0;j<sizeof(AsciiLib)/sizeof(AsciiLib[0]);j++)if((U8)AsciiLib[j].Index==pHz[0])break;//--------------------------if(j<len) //j<len,说明该字已经在汉字中出现{LCD_SetWindows(x, y, x+7, y+15);for (i=0;i<16;i++){str = (U8)AsciiLib[j].Msk[i];for (k=0;k<8;k++){if ( str & (0x80>>k) ) //通过移位逐位发送数据{LCD_WrDat((U16)(LineColor&0xffff));}else{if (Mod == NORMAL){LCD_WrDat((U16)(FillColor&0xffff));}else{LCD_SetGramPoit(x+k+1,y+i); //跳过这一点,即保留该点原有的信息} } } } } }* 名称: DrawSingleHz* 功能: 在指定的位置显示汉字* 参数: 坐标:x* 坐标:y* 字符的颜色:LineColor* 字符背景颜色:FillColor******************************************************************/ void DrawSingleHz(U16 x, U16 y, U8 *pHz, U16 LineColor,U16 FillColor, U8 Mod){U16 i=0,j=0,k=0;U16 str,len;//---------------------------查找该字是否已在字库中len=sizeof(HzLib)/sizeof(HzLib[0]);for(i=0;i<sizeof(HzLib)/sizeof(HzLib[0]);i++)if((U8)HzLib[i].Index[0]==pHz[0]&&(U8)HzLib[i].Index[1]==pHz[1])break; //--------------------------if(i<len) //j<len,说明该字已经在汉字中出现{LCD_SetWindows(x, y, x+15, y+15);for (j=0;j<16;j++){str = (U8)HzLib[i].Msk[j*2]<<8|(U8)HzLib[i].Msk[j*2+1];for (k=0;k<16;k++){if ( str & (0x8000>>k) ) //通过移位逐位发送数据{LCD_WrDat((U16)(LineColor&0xffff));}else{if (Mod == NORMAL){LCD_WrDat((U16)(FillColor&0xffff));}else{LCD_SetGramPoit(x+k+1,y+j);/跳过这一点,即保留该点原有的信息}}}}}}/******************************************************************* 名称: DrawString* 功能: 在指定的位置显示多个字符* 参数: 坐标:x* 坐标:y* 字符的颜色:LineColor* 字符背景颜色:FillColor** 返回值: 无******************************************************************/ void DrawString(U16 x, U16 y, U8 *pStr, U16 LineColor,U16 FillColor, U8 Mod) { //把字符串的第一个字符的地址赋给字符指针变量pstr,//不是*pStr=" "详见濉跺《C程序设计》-谭浩强P252 while(1){if (*pStr == 0){return;}if (*pStr > 0x80) //大于0x80的为汉字{DrawSingleHz(x, y, pStr, LineColor, FillColor, Mod);//调用显示单个汉字函数处理x += 16;pStr += 2;} //移动指针else //英文字符{DrawSingleAscii(x, y, pStr, LineColor, FillColor, Mod);//调用显示单个字符函数处理x += 8;pStr += 1; //移动指针}}}/******************************************************************** * 名称: DispNum* 功能: 显示触摸屏点击处的坐标(用于调试用)* 参数: 坐标竖直要显示的位置:x,y要显示的坐标值存放坐标值的数组名:str* 返回值: 无*******************************************************************/ void DispNum(U16 x, U16 y, U16 num){U8 str[5];str[0] = num/1000+0x30;str[1] = (num%1000)/100+0x30;str[2] = (num%1000)%100/10+0x30;str[3] = (num%1000)%100%10+0x30;str[4] = '\0';DrawString(x, y, str, RED, YELLOW, NORMAL);}/****************************************************************** * 名称: DispSmallPic* 功能: 在指定的位置显示一张65K色的图片* 参数: 显示的起始坐标:x,y图片的宽度和高度:w,h图片数据的数组名:str* 返回值: 无******************************************************************/ void DispSmallPic(U16 x, U16 y, U16 w, U16 h, const U8 *str){U16 i,j,temp;for(j=0;j<h;j++){LCD_SetGramPoit(x,y+j);for(i=0;i<w;i++) //图片数据存放的格式是低字节在前,高字节在后{temp=str[(j*w+i)*2+1]<<8; //发送数据时高字节在前temp|=str[(j*w+i)*2]; //低字节在后LCD_WrDat(temp);}}}。
C51典型例程(按键驱动)
主要(zhǔyào)内容:
1. 键盘(jiànpán) 2. LED数码管 3. 字符型LCD
精品资料
键盘(jiànpán)
1. 独立式键盘(jiànpán)
(1) 独立式键盘的结构 与特点
精品资料
键盘(jiànpán)
1. 独立式键盘(jiànpán)
(2) 编程模式 在确定了键盘的编程结构后,就可以编制键盘接口程序。键盘接口程序 的功能实际上就是驱动键盘工作,完成按键的识别,根据所识别按键的键值, 完成按键子程序的正确散转,从而完成单片机应用系统对用户按键动作的预 定义响应。
形。 (2)16×2字符(zìfú)型LCD引脚说明 16×2字符(zìfú)型LCD共有14个引脚,其功能见表6-3所示。
精品资料
字符(zìfú)型LCD
2. HD44780 驱动器(16×2字符型LCD)
(3)LCD内部的内存 LCD内部存储器共分为3种:固定字形ROM,称为CG(Character
(2) 定时扫描方式
定时扫描方式就是每隔一段时间对键 盘扫描一次,它利用单片机内部的定时 器产生一定时间(例如10ms)的定时, 当定时时间到就产生定时器溢出中断, CPU响应中断后对键盘进行扫描,并在 有键按下时识别出该键,再执行该键的 功能程序。
精品资料
键盘(jiànpán)
4. 键盘(jiànpán)的工作方式
2)忙碌标志(Busy Flag,BF)。当LCD模块内部处于忙碌状态,不能接 收或处理外部信号时,这个标志就会被设定为1,因此在对LCD模块控制时,一 定要先检查这个忙碌标志,当BF=0时,才可以对LCD模块进行控制。
精品资料
字符(zìfú)型LCD
2. HD44780 驱动器(16×2字符型LCD)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
77.
78.#define RX2_EN 0x0 //双频道功能启用
79.#define CM 0x1 //0:Direct mode 1:ShockBurst mode
80.#define RFDR_SB 0x0 //0:250kbps 1:1Mbps
97.#define RFConfig_Byte7 ADDR2_2
98.#define RFConfig_Byte8 ADDR2_1
99.#define RFConfig_Byte9 ADDR2_0
100.#define RFConfig_Byte10 ADDR1_4
101.#define RFConfig_Byte11 ADDR1_3
164./**********************************************************
165.* 2401数据传输接口
166.*详细内容参见2401手册<Configuration mode timing>章节
167.**********************************************************/
116.RFConfig_Byte4,
117.RFConfig_Byte5,
118.RFConfig_Byte6,
119.RFConfig_Byte7,
120.RFConfig_Byte8,
121.RFConfig_Byte9,
122.RFConfig_Fra bibliotekyte10,123.RFConfig_Byte11,
158.for(i=0;i<80;i++);
159.}
160.
161.bdata unsigned char DATA_BUF;
162.#define DATA7 ((DATA_BUF & BYTE_BIT7) != 0)
163.#define DATA0 ((DATA_BUF & BYTE_BIT0) != 0)
168.unsigned char Spi_ByteRead(void)
169.{
170.unsigned char i = 0;
171.for (i=0; i<8; i++)
172.{
173.DATA_BUF = DATA_BUF << 1;
174.CLK1 = 1;
175.DATA = 1; //设置为输入状态
81.#define XO_F 0x3 //16M //nRF2401晶振频率
82.#define RF_PWR 0x3 //信号发射功率
83.
84.#define RF_CH 0x2 //Channel RF频率
85.#define RXEN 0x0//DEF_RXEN //0:Tx 1:Rx
86.//程序会重新设置此项参数
32.// sbit OUT2 = P3^3;
33.sbit CS = P1^1;
34.sbit DR1 = P1^0;
35.sbit CLK1 = P3^7;
36.sbit DATA = P3^3;
37.
38.sbit LED0 = P3^4;
39.sbit LED1 = P3^5;
40.sbit KEY0 = P3^0;
102.#define RFConfig_Byte12 ADDR1_2
103.#define RFConfig_Byte13 ADDR1_1
104.#define RFConfig_Byte14 ADDR1_0
105.#define RFConfig_Byte15 (ADDR_W<<2 | CRC_L<<1 | CRC_EN)
138.* void SetTxMode(void); //设置为发送模式
139.* void SetRxMode(void); //设置为接收模式
140.* void nRF2401_TxPacket(unsigned char TxBuf[]);
141.* //发送TxBuf[]内的数据长度由DATA1_W决定
87.
88.//-----------------------------------------------------------
89.//<将设置信息组合成每个字节的数据信息,此区域无需修改>
90.#define RFConfig_Byte0 TEST_2
91.#define RFConfig_Byte1 TEST_1
56.
57.// 0xE0 = 224
58.//16bit Address + 224bit(28byte)Data + 16bit CRC = 256bit
59.
60./*注意:2401忽略ADDR中超过ADDR_W设定宽度的那些位,同时地址不能全部设置为0 */
61.//频道2接收地址(当前模块地址)
5.// Date: 2007-3-12
6.// Update 2007-9-8
7.////////////////////////////////////////////////////////////////////
8.//这是我购买在nRF2401时从开发商中得到的代码。我已经验证过。
9.//供大家学习用,只要修改下代码就可以应用到其他的单片机。
nRF2401的C51驱动程序[已经调试通过]
复制代码
1.
2./////////////////////////////////////////////////////////////////////
3.// Desc: Demo App for RF2401 Module
4.// Vender:
146.
147.//16M晶振600us左右
148.void Delay100(void)
149.{
150.unsigned int i;
151.for(i=0;i<100;i++);
152.}
153.
154.void Delay(uchar n)
155.{
156.uint i;
157.while(n--)
133./**************************************************************
134.* nRF2401 Tx/Rx functions
135.*
136.* void Delay100(void);
137.* void Config2401(void); //配置2401,写入初始化设置
20.#define BYTE_BIT2 0x04
21.#define BYTE_BIT3 0x08
22.#define BYTE_BIT4 0x10
23.#define BYTE_BIT5 0x20
24.#define BYTE_BIT6 0x40
25.#define BYTE_BIT7 0x80
62.#define ADDR2_4 0x00
63.#define ADDR2_3 0x1c
64.#define ADDR2_2 0xcc
65.#define ADDR2_1 0xcc
66.#define ADDR2_0 0xcc
67.//频道1接收地址
68.#define ADDR1_4 0x00
52.
53./*注意: DATAx_W + ADDRx_W + CRC的值必须小于256 !单个数据包的大小必须小于32字节(256位) */
54.#define DATA2_W 0x10 //2字节//频道2数据长度(单位:Bit)
55.#define DATA1_W 0xE0 //28字节//频道1数据长度(单位:Bit)
10.//这个程序是一个半双工的通信模式.
11.//
12.//
13.#include <reg51.h>
14.//常量定义
15.#define uchar unsigned char
16.#define uint unsigned int
17.
18.#define BYTE_BIT0 0x01
19.#define BYTE_BIT1 0x02
69.#define ADDR1_3 0xcc
70.#define ADDR1_2 0xcc
71.#define ADDR1_1 0xcc
72.#define ADDR1_0 0xcc
73.
74.#define ADDR_W 0x10 //2字节//接收地址宽度(单位:Bit)
75.#define CRC_L 0x1 //CRC模式0:8位1:16
92.#define RFConfig_Byte2 TEST_0
93.#define RFConfig_Byte3 DATA2_W
94.#define RFConfig_Byte4 DATA1_W
95.#define RFConfig_Byte5 ADDR2_4
96.#define RFConfig_Byte6 ADDR2_3
47./*=====<RF-Configuration-Register配置信息>=====*/
48.//芯片测试用,无需修改
49.#define TEST_2 0x8E //MSB D143~D136
50.#define TEST_1 0x08 // D135~D128