完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
//-----------------------函数声明,变量定义------------------------ #include #include "api.h" #include #define uchar unsigned char #define uint unsigned int /***************************************************/ #define TX_ADR_WIDTH 5 // 5字节宽度的发送/接收地址 #define TX_PLOAD_WIDTH 4 // 数据通道有效数据宽度 #define LED P2 #define G 13.2 /*定值eg:13.2*/ uchar TEMP; uchar code TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01}; // 定义一个静态发送地址 uchar RX_BUF[TX_PLOAD_WIDTH]; uchar TX_BUF[TX_PLOAD_WIDTH]; uchar flag; uchar DATA = 0x01; uchar bdata sta; ***it RX_DR = sta^6; ***it TX_DS = sta^5; ***it MAX_RT = sta^4; /**************************************************/ ***it SCL=P3^4; // 将p1.2口模拟时钟口 ***it SDA=P3^5; // 将p1.3口模拟数据口 bit askflag; #define disdata P0 //显示数据码输出口 ***it LCD_RS = P2^0; ***it LCD_RW = P2^1; ***it LCD_EN = P2^2; uint data dis[4]={0x00,0x00,0x00,0x00}; //定义3个显示数据单元和1个数据存储单元 uchar code dis4[] = {" OUT AD Value(V)"}; uchar code dis5[] = {"V= . V "}; #define delayNOP(); {_nop_();_nop_();_nop_();_nop_();}; bit bdata SystemError; //从机错误标志位 /*********************** PCF8591专用变量定义 ***********************/ #define PCF8591_WRITE 0x90 #define PCF8591_READ 0x91 #define NUM 1 //接收和发送缓存区的深度 uchar idata receivebuf[NUM]; //数据接收缓冲区 /****************************************************************************************************************************************************** 函数: init_io() 描述: 初始化IO /******************************************************************************************************************************************************/ void init_io(void) { CE = 0; // 待机 CSN = 1; // SPI禁止 SCK = 0; // SPI时钟置低 IRQ = 1; // 中断复位 LED = 0xff; // 关闭指示灯 } /**************************************************/ /************************************************** 函数:delay_ms() 描述: 延迟x毫秒 /**************************************************/ void delay_ms(uchar x) { uchar i, j; i = 0; for(i=0; i j = 250; while(--j); j = 250; while(--j); } } /**************************************************/ /************************************************** 函数:SPI_RW() 描述: 根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01 读出一字节 /**************************************************/ uchar SPI_RW(uchar byte) { uchar i; for(i=0; i<8; i++) // 循环8次 { MOSI = (byte & 0x80); // byte最高位输出到MOSI byte <<= 1; // 低一位移位到最高位 SCK = 1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据 byte |= MISO; // 读MISO到byte最低位 SCK = 0; // SCK置低 } return(byte); // 返回读出的一字节 } /**************************************************/ /************************************************** 函数:SPI_RW_Reg() 描述: 写数据value到reg寄存器 /**************************************************/ uchar SPI_RW_Reg(uchar reg, uchar value) { uchar status; CSN = 0; // CSN置低,开始传输数据 status = SPI_RW(reg); // 选择寄存器,同时返回状态字 SPI_RW(value); // 然后写数据到该寄存器 CSN = 1; // CSN拉高,结束数据传输 return(status); // 返回状态寄存器 } /**************************************************/ /************************************************** 函数:SPI_Read() 描述: 从reg寄存器读一字节 /**************************************************/ uchar SPI_Read(uchar reg) { uchar reg_val; CSN = 0; // CSN置低,开始传输数据 SPI_RW(reg); // 选择寄存器 reg_val = SPI_RW(0); // 然后从该寄存器读数据 CSN = 1; // CSN拉高,结束数据传输 return(reg_val); // 返回寄存器数据 } /**************************************************/ /************************************************** 函数:SPI_Read_Buf() 描述: 从reg寄存器读出bytes个字节,通常用来读取接收通道 数据或接收/发送地址 /**************************************************/ uchar SPI_Read_Buf(uchar reg, uchar * pBuf, uchar bytes) { uchar status, i; CSN = 0; // CSN置低,开始传输数据 status = SPI_RW(reg); // 选择寄存器,同时返回状态字 for(i=0; i CSN = 1; // CSN拉高,结束数据传输 return(status); // 返回状态寄存器 } /**************************************************/ /************************************************** 函数:SPI_Write_Buf() 描述: 把pBuf缓存中的数据写入到nRF24L01,通常用来写入发 射通道数据或接收/发送地址 /**************************************************/ uchar SPI_Write_Buf(uchar reg, uchar * pBuf, uchar bytes) { uchar status, i; CSN = 0; // CSN置低,开始传输数据 status = SPI_RW(reg); // 选择寄存器,同时返回状态字 for(i=0; i CSN = 1; // CSN拉高,结束数据传输 return(status); // 返回状态寄存器 } /**************************************************/ /************************************************** 函数:RX_Mode() 描述: 这个函数设置nRF24L01为接收模式,等待接收发送设备的数据包 /**************************************************/ void RX_Mode(void) { CE = 0; SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 接收设备接收通道0使用和发送设备相同的发送地址 SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 使能接收通道0自动应答 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0 SPI_RW_Reg(WRITE_REG + RF_CH, 40); // 选择射频通道0x40 SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // 接收通道0选择和发送通道相同有效数据宽度 SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益 SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // CRC使能,16位CRC校验,上电,接收模式 CE = 1; // 拉高CE启动接收设备 } /**************************************************/ /************************************************** 函数:TX_Mode() 描述: 这个函数设置nRF24L01为发送模式,(CE=1持续至少10us), 130us后启动发射,数据发送结束后,发送模块自动转入接收 模式等待应答信号。 /**************************************************/ void TX_Mode(uchar * BUF) { CE = 0; SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写入发送地址 SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 为了应答接收设备,接收通道0地址和发送地址相同 SPI_Write_Buf(WR_TX_PLOAD, BUF, TX_PLOAD_WIDTH); // 写数据包到TX FIFO SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 使能接收通道0自动应答 SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0 SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x0a); // 自动重发延时等待250us+86us,自动重发10次 SPI_RW_Reg(WRITE_REG + RF_CH, 40); // 选择射频通道0x40 SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益 SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // CRC使能,16位CRC校验,上电 CE = 1; } /**************************************************/ /************************************************** 函数:Check_ACK() 描述: 检查接收设备有无接收到数据包,设定没有收到应答信 号是否重发 /**************************************************/ uchar Check_ACK(bit clear) { while(IRQ); sta = SPI_RW(NOP); // 返回状态寄存器 if(MAX_RT) if(clear) // 是否清除TX FIFO,没有清除在复位MAX_RT中断标志后重发 SPI_RW(FLUSH_TX); SPI_RW_Reg(WRITE_REG + STATUS, sta); // 清除TX_DS或MAX_RT中断标志 IRQ = 1; if(TX_DS) return(0x00); else return(0xff); } /**************************************************/ /************************************************** 函数:CheckButtons() 描述: 检查按键是否按下,按下则发送一字节数据 /**************************************************/ void CheckButtons() { unsigned char AD; AD=TEMP; if(AD!=G) /*硬件距离固定了G为固定值*/ { delay_ms(20); if(AD!=G)//基准电压 // 此处数据需要修改 判断条件修改为 判断 此时采集的电压与基准电压(硬件距离固定的话 基准电压不变)是否相同 { TX_BUF[0] = ~DATA; // 数据送到缓存 TX_Mode(TX_BUF); // 把nRF24L01设置为发送模式并发送数据 // LED = ~DATA; // 数据送到LED显示 //此处可以修改为指示灯 Check_ACK(1); // 等待发送完毕,清除TX FIFO delay_ms(250); delay_ms(250); // LED = 0xff; // 关闭LED //此处可以修改为指示灯 } } } /******************************************************************************************************************************************************/ /*******************************************************************/ /* */ /* 延时函数 */ /* */ /*******************************************************************/ void delay(int ms) { while(ms--) { uchar i; for(i=0;i<250;i++) { _nop_(); _nop_(); _nop_(); _nop_(); } } } /*******************************************************************/ /* */ /*检查LCD忙状态 */ /*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。 */ /* */ /*******************************************************************/ bit lcd_busy() { bit result; LCD_RS = 0; LCD_RW = 1; LCD_EN = 1; delayNOP(); result = (bit)(P0&0x80); LCD_EN = 0; return(result); } /*******************************************************************/ /* */ /*写指令数据到LCD */ /*RS=L,RW=L,E=高脉冲,D0-D7=指令码。 */ /* */ /*******************************************************************/ void lcd_wcmd(uchar cmd) { while(lcd_busy()); LCD_RS = 0; LCD_RW = 0; LCD_EN = 0; _nop_(); _nop_(); P0 = cmd; delayNOP(); LCD_EN = 1; delayNOP(); LCD_EN = 0; } /*******************************************************************/ /* */ /*写显示数据到LCD */ /*RS=H,RW=L,E=高脉冲,D0-D7=数据。 */ /* */ /*******************************************************************/ void lcd_wdat(uchar dat) { while(lcd_busy()); LCD_RS = 1; LCD_RW = 0; LCD_EN = 0; P0 = dat; delayNOP(); LCD_EN = 1; delayNOP(); LCD_EN = 0; } /*******************************************************************/ /* */ /* LCD初始化设定 */ /* */ /*******************************************************************/ void lcd_init() { delay(15); lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据 delay(5); lcd_wcmd(0x38); delay(5); lcd_wcmd(0x38); delay(5); lcd_wcmd(0x0c); //显示开,关光标 delay(5); lcd_wcmd(0x06); //移动光标 delay(5); lcd_wcmd(0x01); //清除LCD的显示内容 delay(5); } /*******************************************************************/ /* */ /* 设定显示位置 */ /* */ /*******************************************************************/ void lcd_pos(uchar pos) { lcd_wcmd(pos | 0x80); //数据指针=80+地址变量 } /******************************************************************/ /* */ /* 数据处理与显示 */ /* 将采集到的数据进行16进制转换为ASCLL码。 */ /* */ /******************************************************************/ show_value(uchar ad_data) { dis[2]=ad_data/51; //AD值转换为3为BCD码,最大为5.00V。 dis[2]=dis[2]+0x30; //转换为ACSII码 dis[3]=ad_data%51; //余数暂存 dis[3]=dis[3]*10; //计算小数第一位 dis[1]=dis[3]/51; dis[1]=dis[1]+0x30; //转换为ACSII码 dis[3]=dis[3]%51; dis[3]=dis[3]*10; //计算小数第二位 dis[0]=dis[3]/51; dis[0]=dis[0]+0x30; //转换为ACSII码 } /****************************************************************************************************************************************************** ******************************************************************************************************************************************************/ //------------------------------------------------------------------- // 函数名称: iic_start() // 函数功能: 启动I2C总线子程序 //------------------------------------------------------------------- void iic_start(void) { //时钟保持高,数据线从高到低一次跳变,I2C通信开始 SDA = 1; SCL = 1; delayNOP(); // 延时5us SDA = 0; delayNOP(); SCL = 0; } //------------------------------------------------------------------- // 函数名称: iic_stop() // 函数功能: 停止I2C总线数据传送子程序 //------------------------------------------------------------------- void iic_stop(void) { SDA = 0; //时钟保持高,数据线从低到高一次跳变,I2C通信停止 SCL = 1; delayNOP(); SDA = 1; delayNOP(); SCL = 0; } //------------------------------------------------------------------ // 函数名称: iicInit_() // 函数功能: 初始化I2C总线子程序 //------------------------------------------------------------------ void iicInit(void) { SCL = 0; iic_stop(); } //------------------------------------------------------------------- // 函数名称: slave_ACK // 函数功能: 从机发送应答位子程序 //------------------------------------------------------------------- void slave_ACK(void) { SDA = 0; SCL = 1; delayNOP(); SCL = 0; } //------------------------------------------------------------------- // 函数名称: slave_NOACK // 函数功能: 从机发送非应答位子程序,迫使数据传输过程结束 //------------------------------------------------------------------- void slave_NOACK(void) { SDA = 1; SCL = 1; delayNOP(); SDA = 0; SCL = 0; } //------------------------------------------------------------------- // 函数名称: check_ACK // 函数功能: 主机应答位检查子程序,迫使数据传输过程结束 //------------------------------------------------------------------- void check_ACK(void) { SDA = 1; // 将p1.1设置成输入,必须先向端口写1 SCL = 1; askflag = 0; delayNOP(); if(SDA == 1) // 若SDA=1表明非应答,置位非应答标志askflag askflag = 1; SCL = 0; } //------------------------------------------------------------------- // 函数名称: IICSendByte // 入口参数: ch // 函数功能: 发送一个字节 //------------------------------------------------------------------- void IICSendByte(uchar ch) { unsigned char idata n=8; // 向SDA上发送一位数据字节,共八位 while(n--) { if((ch&0x80) == 0x80) // 若要发送的数据最高位为1则发送位1 { SDA = 1; // 传送位1 SCL = 1; delayNOP(); // SDA = 0; SCL = 0; } else { SDA = 0; // 否则传送位0 SCL = 1; delayNOP(); SCL = 0; } ch = ch<<1; // 数据左移一位 } } //------------------------------------------------------------------- // 函数名称: IICreceiveByte // 返回接收的数据 // 函数功能: 接收一字节子程序 //------------------------------------------------------------------- uchar IICreceiveByte(void) { uchar idata n=8; // 从SDA线上读取一上数据字节,共八位 uchar tdata=0; while(n--) { SDA = 1; SCL = 1; tdata =tdata<<1; //左移一位 if(SDA == 1) tdata = tdata|0x01; // 若接收到的位为1,则数据的最后一位置1 else tdata = tdata&0xfe; // 否则数据的最后一位置0 SCL = 0; } return(tdata); } //------------------------------------------------------------------- // 函数名称: DAC_PCF8591 // 入口参数: slave_add从机地址,n要发送的数据个数 // 函数功能: 发送n位数据子程序 //------------------------------------------------------------------- void DAC_PCF8591(uchar controlbyte,uchar w_data) { iic_start(); // 启动I2C delayNOP(); IICSendByte(PCF8591_WRITE); // 发送地址位 check_ACK(); // 检查应答位 if(askflag == 1) { SystemError = 1; return; // 若非应答,置错误标志位 } IICSendByte(controlbyte&0x77); //Control byte check_ACK(); //检查应答位 if(askflag == 1) { SystemError = 1; return; // 若非应答,置错误标志位 } IICSendByte(w_data); //data byte check_ACK(); // 检查应答位 if(askflag == 1) { SystemError = 1; return; // 若非应答表明器件错误或已坏,置错误标志位SystemError } iic_stop(); // 全部发完则停止 delayNOP(); delayNOP(); delayNOP(); delayNOP(); } //------------------------------------------------------------------- // 函数名称: ADC_PCF8591 // 入口参数: controlbyte控制字 // 函数功能: 连续读入4路通道的A/D转换结果到receivebuf //------------------------------------------------------------------- void ADC_PCF8591(uchar controlbyte) { uchar idata receive_da,i=0; iic_start(); IICSendByte(PCF8591_WRITE); //控制字 check_ACK(); if(askflag == 1) { SystemError = 1; return; } IICSendByte(0x40|controlbyte); //控制字 check_ACK(); if(askflag == 1) { SystemError = 1; return; } iic_start(); //重新发送开始命令 IICSendByte(PCF8591_READ); //控制字 check_ACK(); if(askflag == 1) { SystemError = 1; return; } IICreceiveByte(); //空读一次,调整读顺序 slave_ACK(); //收到一个字节后发送一个应答位 receive_da=IICreceiveByte(); receivebuf[1]=receive_da; // slave_ACK(); //收到一个字节后发送一个应答位 slave_NOACK(); //收到最后一个字节后发送一个非应答位 iic_stop(); } /****************************************************************************************************************************************************** // 主程序 // ******************************************************************************************************************************************************/ //------------------------------------------------------------------- // 函数名称: main // 函数功能: 主程序 //------------------------------------------------------------------- main() { uchar i,l; init_io(); // 初始化IO TX_Mode(TX_BUF); delay(10); //延时 lcd_init(); //初始化LCD lcd_pos(0); //设置显示位置为第一行的第1个字符 i = 0; while(dis4 != ' |