OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5513|回复: 0

STM32F103RCT6正点原子mini板,用串口1串口4接收超声波测距数据,用24L01模块进行无线通信,出现串口数据错误问题

[复制链接]

3

主题

14

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2016-12-27
在线时间
14 小时
发表于 2017-6-25 12:00:38 | 显示全部楼层 |阅读模式
4金钱
STM32F103RCT6正点原子mini板,用串口1串口4接收两路超声波测距数据(波特率9600),用24L01模块进行无线通信(主要发送一些距离范围内的状态),出现串口数据错误问题:
具体情况:              当使用上述功能时,发现拔掉串口的RX数据线,并不影响结果,意思就是测距的数据并没有被STM32读取和用于计算,请问是不是2.4g无线对串口有影响??
第一段程序为串口1初始化:
[mw_shl_code=c,true]#include "usart.h"
//////////////////////////////////////////////////////////////////////////////////          
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"                                        //ucos 使用          
#endif
//////////////////////////////////////////////////////////////////////////////////         
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32开发板
//串口1初始化                  
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/8/18
//版本:V1.5
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
//********************************************************************************
//V1.3修改说明
//支持适应不同频率下的串口波特率设置.
//加入了对printf的支持
//增加了串口接收命令功能.
//修正了printf第一个字符丢失的bug
//V1.4修改说明
//1,修改串口初始化IO的bug
//2,修改了USART_RX_STA,使得串口最大接收字节数为2的14次方
//3,增加了USART_REC_LEN,用于定义串口最大允许接收的字节数(不大于2的14次方)
//4,修改了EN_USART1_RX的使能方式
//V1.5修改说明
//1,增加了对UCOSII的支持
//////////////////////////////////////////////////////////////////////////////////           


//////////////////////////////////////////////////////////////////
//加入以下代码,支持printf函数,而不需要选择use MicroLIB          
#if 1
#pragma import(__use_no_semihosting)            
//标准库需要的支持函数                 
struct __FILE
{
        int handle;

};

FILE __stdout;      
//定义_sys_exit()以避免使用半主机模式   
_sys_exit(int x)
{
        x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{      
        while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
        return ch;
}
#endif



#if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误          
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,        接收完成标志
//bit14,        接收到0x0d
//bit13~0,        接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记          
u8  num = 0;           //接收到的数据个数
  
void uart_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
         
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);        //使能USART1,GPIOA时钟
  
        //USART1_TX   GPIOA.9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
   
  //USART1_RX          GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;                //子优先级3
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
        NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器
  
   //USART 初始化设置

        USART_InitStructure.USART_BaudRate = bound;//串口波特率
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
        USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
        USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //收发模式

  USART_Init(USART1, &USART_InitStructure); //初始化串口1
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(USART1, ENABLE);                    //使能串口1

}

void USART1_IRQHandler(void)                        //串口1中断服务程序
        {
        u8 Res;
#if SYSTEM_SUPPORT_OS                 //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
        OSIntEnter();   
#endif
        if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
                {
                Res =USART_ReceiveData(USART1);        //读取接收到的数据
                //USART_SendData(USART1,Res);//每接收一次数据  给串口发送一个0x88
         // while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
                if(Res == 0xff)//接收到OxFF
                        {
                                USART_RX_STA = 1;
                                num = 0;       
                        }  
                if(USART_RX_STA == 1)  //数据有效就接收
                {
                                USART_RX_BUF[num++] = Res;
                                if(num>=4)
                                        USART_RX_STA = 0;       
                }
     }
#if SYSTEM_SUPPORT_OS         //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
        OSIntExit();                                                                                           
#endif
}
#endif       
[/mw_shl_code]第二段程序为串口4初始化:
[mw_shl_code=c,true]#include "usart4.h"          
//////////////////////////////////////////////////////////////////////////////////          
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"                                        //ucos 使用          
#endif

//串口5初始化                    

#if EN_USART4_RX   //如果使能了接收
//串口5中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误          
u8 USART4_RX_BUF[USART4_REC_LEN];     //接收缓冲,最大USART4_REC_LEN个字节.
//接收状态
//bit15,        接收完成标志
//bit14,        接收到0x0d
//bit13~0,        接收到的有效字节数目
u16 USART4_RX_STA=0;       //接收状态标记          
u8  num1 = 0;           //接收到的数据个数
//PD2 PC12  
void uart4_init(u32 bound){
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
         
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);        //使能GPIOC时钟
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4,ENABLE);//使能USART4时钟
  
//        //USART4_TX   GPIOC.10
//  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PC.10
//  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        //复用推挽输出
//  GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC.10
   
  //USART4_RX          GPIOC.11初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PC11
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOD.2  

  //Usart4 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级1
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;                //子优先级2
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQ通道使能
        NVIC_Init(&NVIC_InitStructure);        //根据指定的参数初始化VIC寄存器
  
   //USART 初始化设置

        USART_InitStructure.USART_BaudRate = bound;//串口波特率
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
        USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
        USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
//        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //收发模式
        USART_InitStructure.USART_Mode = USART_Mode_Rx;//收模式

  USART_Init(UART4, &USART_InitStructure); //初始化串口4
  USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(UART4, ENABLE);                    //使能串口4

}

void UART4_IRQHandler(void)                        //串口4中断服务程序
        {
        u8 Res;
#if SYSTEM_SUPPORT_OS                 //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
        OSIntEnter();   
#endif
        if(USART_GetITStatus(UART4, USART_IT_RXNE) != RESET)  //接收中断
                {
                Res =USART_ReceiveData(UART4);        //读取接收到的数据
                if(Res == 0xff)//接收到OxFF
                        {
                                USART4_RX_STA = 1;
                                num1 = 0;       
                        }  
                if(USART4_RX_STA == 1)  //数据有效就接收
                {
                                USART4_RX_BUF[num1++] = Res;
                                if(num1>=4)
                                        USART4_RX_STA = 0;       
                }
     }
#if SYSTEM_SUPPORT_OS         //如果SYSTEM_SUPPORT_OS为真,则需要支持OS.
        OSIntExit();                                                                                           
#endif
}
#endif       
[/mw_shl_code]
第三段程序为24L01初始化程序:
[mw_shl_code=c,true]#include "24l01.h"

//////////////////////////////////////////////////////////////////////////////////         
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK MiniSTM32开发板
//NRF24L01驱动代码          
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2014/3/12
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼v电子科技有限公司 2009-2019
//All rights reserved                                                                          
//////////////////////////////////////////////////////////////////////////////////
   
const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //发送地址
const u8 RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //发送地址

u8 date_buf[6]="6000R"; //数据缓冲区 ,窗户状态/小孩/雨滴,用于发送
u8 ctrl_buf[2][6]={"dddqq","dddqq"}; //控制指令缓冲区,需要控制的硬件在这里注册一下,用于接收上位机指令,D:自动/手动 W:开窗/关窗


//初始化24L01的IO口

void NRF24L01_Init(void)
{  
        GPIO_InitTypeDef GPIO_InitStructure;
        SPI_InitTypeDef  SPI_InitStructure;
       
        RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC, ENABLE );       
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOC, &GPIO_InitStructure);
        GPIO_SetBits(GPIOC,GPIO_Pin_4);
       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU  ;   //上拉输入
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        GPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4);
        SPI1_Init();                    //初始化SPI
               
        SPI_Cmd(SPI1, DISABLE); //
       
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                //设置SPI工作模式:设置为主SPI
        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                //设置SPI的数据大小:SPI发送接收8位帧结构
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                //选择了串行时钟的稳态:时钟悬空低电平
        SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;        //数据捕获于第一个时钟沿
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;                //定义波特率预分频的值:波特率预分频值为256
        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;        //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
        SPI_InitStructure.SPI_CRCPolynomial = 7;        //CRC值计算的多项式
        SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

       
        NRF24L01_CE=0;         //使能24L01
        NRF24L01_CSN=1;        //SPI片选取消                
}
//检测24L01是否存在
//返回值:0,成功;1,失败       
u8 NRF24L01_Check(void)
{
        u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
        u8 i;
        SPI1_SetSpeed(SPI_BaudRatePrescaler_8); //spi速度为9Mhz(24L01的最大SPI时钟为10Mhz)            
        NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,buf,5);//写入5个字节的地址.       
        NRF24L01_Read_Buf(TX_ADDR,buf,5); //读出写入的地址  
        for(i=0;i<5;i++)if(buf!=0XA5)break;                                                                   
        if(i!=5)return 1;//检测24L01错误       
        return 0;                 //检测到24L01
}                  
//SPI写寄存器
//reg:指定寄存器地址
//value:写入的值
u8 NRF24L01_Write_Reg(u8 reg,u8 value)
{
        u8 status;       
           NRF24L01_CSN=0;                 //使能SPI传输
          status =SPI1_ReadWriteByte(reg);//发送寄存器号
          SPI1_ReadWriteByte(value);      //写入寄存器的值
          NRF24L01_CSN=1;                 //禁止SPI传输          
          return(status);                               //返回状态值
}
//读取SPI寄存器值
//reg:要读的寄存器
u8 NRF24L01_Read_Reg(u8 reg)
{
        u8 reg_val;            
        NRF24L01_CSN = 0;          //使能SPI传输               
          SPI1_ReadWriteByte(reg);   //发送寄存器号
          reg_val=SPI1_ReadWriteByte(0XFF);//读取寄存器内容
          NRF24L01_CSN = 1;          //禁止SPI传输                    
          return(reg_val);           //返回状态值
}       
//在指定位置读出指定长度的数据
//reg:寄存器(位置)
//*pBuf:数据指针
//len:数据长度
//返回值,此次读到的状态寄存器值
u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len)
{
        u8 status,u8_ctr;               
          NRF24L01_CSN = 0;           //使能SPI传输
          status=SPI1_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值             
        for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=SPI1_ReadWriteByte(0XFF);//读出数据
          NRF24L01_CSN=1;       //关闭SPI传输
          return status;        //返回读到的状态值
}
//在指定位置写指定长度的数据
//reg:寄存器(位置)
//*pBuf:数据指针
//len:数据长度
//返回值,此次读到的状态寄存器值
u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len)
{
        u8 status,u8_ctr;            
        NRF24L01_CSN = 0;          //使能SPI传输
          status = SPI1_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值
          for(u8_ctr=0; u8_ctr<len; u8_ctr++)SPI1_ReadWriteByte(*pBuf++); //写入数据         
          NRF24L01_CSN = 1;       //关闭SPI传输
          return status;          //返回读到的状态值
}                                  
//启动NRF24L01发送一次数据
//txbuf:待发送数据首地址
//返回值:发送完成状况
u8 NRF24L01_TxPacket(u8 *txbuf)
{
        u8 sta;
        SPI1_SetSpeed(SPI_BaudRatePrescaler_8);//spi速度为9Mhz(24L01的最大SPI时钟为10Mhz)   
        NRF24L01_CE=0;
          NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//写数据到TX BUF  32个字节
        NRF24L01_CE=1;//启动发送          
//        while(NRF24L01_IRQ!=0);//等待发送完成
        delay_ms(2);
        sta=NRF24L01_Read_Reg(STATUS);  //读取状态寄存器的值          
        NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志
        if(sta&MAX_TX)//达到最大重发次数
        {
                NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器
                return MAX_TX;
        }
        if(sta&TX_OK)//发送完成
        {
                return TX_OK;
        }
        return 0xff;//其他原因发送失败
}
//启动NRF24L01发送一次数据
//txbuf:待发送数据首地址
//返回值:0,接收完成;其他,错误代码
void NRF24L01_RxPacket(u8 *rxbuf)
{
        u8 sta;                                                                              
        SPI1_SetSpeed(SPI_BaudRatePrescaler_8); //spi速度为9Mhz(24L01的最大SPI时钟为10Mhz)   
        sta=NRF24L01_Read_Reg(STATUS);  //读取状态寄存器的值             
        NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志
//        if(sta&RX_OK)//接收到数据
//        {
                NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
                NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
                        LED1=!LED1;
        delay_ms(50);
                switch (rxbuf[0])
                {
                        case '7'://从机号标志
                                switch (rxbuf[4])
                                {
                                       
                                        case 'D': //自动/手动控制
                                                                                ctrl_buf[0][0]=rxbuf[0];
                                                                                ctrl_buf[0][1]=rxbuf[1];
                                                                                ctrl_buf[0][2]=rxbuf[2];
                                                                                ctrl_buf[0][3]=rxbuf[3];
                                                                                ctrl_buf[0][4]=rxbuf[4];
//                                printf("B%s",&ctrl_buf[0][0]);
                                                                                break;
                                        case 'W'://窗子1开0关
                                                                                ctrl_buf[1][0]=rxbuf[0];
                                                                                ctrl_buf[1][1]=rxbuf[1];
                                                                                ctrl_buf[1][2]=rxbuf[2];
                                                                                ctrl_buf[1][3]=rxbuf[3];
                                                                                ctrl_buf[1][4]=rxbuf[4];
//                                        printf("h%d",rxbuf[3]);
//                                        printf("A%s",&ctrl_buf[1][0]);
                                                                                break;
                                       
                                        default: break;
                                }break;
                        default: break;
                }       

}                                            
//该函数初始化NRF24L01到RX模式
//设置RX地址,写RX数据宽度,选择RF频道,波特率和LNA HCURR
//当CE变高后,即进入RX模式,并可以接收数据了                  
void NRF24L01_RX_Mode(void)
{
        NRF24L01_CE=0;          
          NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址
          
          NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);            //使能通道0的自动应答   
          NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);        //使能通道0的接收地址           
          NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);                    //设置RF通信频率                  
          NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度             
          NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);        //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   
          NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);                //配置基本工作模式的参数WR_UP,EN_CRC,16BIT_CRC,接收模式
          NRF24L01_CE = 1; //CE为高,进入接收模式
}                                                 
//该函数初始化NRF24L01到TX模式
//设置TX地址,写TX数据宽度,设置RX自动应答的地址,填充TX发送数据,选择RF频道,波特率和LNA HCURR
//PWR_UP,CRC使能
//当CE变高后,即进入RX模式,并可以接收数据了                  
//CE为高大于10us,则启动发送.         
void NRF24L01_TX_Mode(void)
{                                                                                                                 
        NRF24L01_CE=0;            
          NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址
          NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK          

          NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);     //使能通道0的自动应答   
          NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址  
          NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
          NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);       //设置RF通道为40
          NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);  //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   
          NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);    //配置基本工作模式的参数WR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
        NRF24L01_CE=1;//CE为高,10us后启动发送
}


//void NRF24L01_POW_DOWN(void)
//{                                                                                                                 
//        NRF24L01_CE=0;            

//        NRF24L01_CE=1;//CE为高,10us后启动发送
//}






[/mw_shl_code]
第四段为主函数:
[mw_shl_code=applescript,true]#include "main.h"
/*窗户控制部分*/
//硬件接口:串口1  PA10 接雷达1
//         串口4  PC11 接雷达2
//         TIM3   PB0\PB1 接电机 PWM输出
//         PA11   雨滴模块
//                                 PD2    LED1灯,用于检测NRF24L01模块,未连接时灯亮
//         液晶   9341  320*240像素(由于使用PB0、PB1输出PWM,所以液晶显示不能用)
//         按键   KEY0(PC5) KEY1(PA15)
//功能:下雨或者有小孩靠近窗户时,向用户发送消息(只发送下雨和有小孩靠近,其余在手机端显示为晴和无人靠近),
//      可由用户决定是否关窗,开窗,也可自动控制

u8 WINDOW_STA = 0;//窗户当前状态 1:开窗状态
u8 OPEN_WIN_STA = 0;//开窗户
u8 CLOSE_WIN_STA = 0;//关窗户
u8 AUTO_CONTORL_STA = 0;//1:自动控制,0:手动控制
u8 RAIN_Flag = 0;//开窗时是否下雨,1:下雨
u8 RAIN_AFlag = 0;//雨后开窗启动标志位,1:雨后
u8 RAIN_temp_Flag = 0;//是否是下雨后关的窗,1:是
u8 CHILD_CHECK_STA = 0;//检测孩子的标志位,1:有孩子在窗户前
u8 CHILD_STA = 0;//检测孩子是否逗留标志位,1:有孩子在窗户逗留
u8 CONTORL_STA = 0;//检测是否自主控制窗户

int main(void)
{       
        static u8 temp = 0;
        delay_init();                     //延时函数初始化         
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
        uart_init(9600);         //串口初始化为9600       
        uart4_init(9600);       
  KEY_Init();
        LED_Init();
        NRF24L01_Init();         
        Rain_Init();
        TIM3_PWM_Init(999,35);//PWM频率=72000000/(999+1)/(35+1)=2Khz 0.5ms
        TIM5_Int_Init(499,7199);//time=(499+1)/72000000/(7199+1)=50ms
        while(NRF24L01_Check())//检查NRF24L01是否在位.不在LED1灯亮
        {
                LED1 = 0;
        }
        LED1 = 1;
        NRF24L01_RX_Mode();//接收模式       

  while(1)
        {               
                NRF24L01_RxPacket(recive_buff);
                //如果有新的数据到达
                delay_ms(2);
               
/*----------------发送和接收数据---------------*/
               
                Communication();//调用一次收发函数
               
/*----------------下雨状态检测---------------*/
               
                if((OPEN_WIN_STA == 0)&&(CLOSE_WIN_STA == 0))//电机不动时进行检测,避免电机状态变化太快
                {       
                        Rain_Show();//下雨检测
                        if(RAIN_STA == 1)//下雨
                        {
                                RAIN_STA = 0;
                                date_buf[3] = '1';//发送“下雨了”
                                if(WINDOW_STA == 1)//窗户当前为打开状态
                                {
                                        RAIN_Flag = 1;//下雨关窗控制标志位
                                }
                        }
                        else
                        {
                                date_buf[3] = '0';//发送“晴天”
                                if(RAIN_temp_Flag == 1)
                                {
                                        RAIN_AFlag = 1;//雨后天晴标志位
                                }
                        }
                       
        /*----------------有小孩状态检测---------------*/
                       
                        if(WINDOW_STA == 1)//窗户当前为打开状态就检测
                        {
                                Distance_compare();//距离检测
                                /*检测是否为小孩*/
                                if(DISTANCE2_STA == 0) //高处传感器为0
                                {               
                                        if(DISTANCE1_STA == 1)
                                        {       
                                                DISTANCE2_STA = 0;
                                                DISTANCE1_STA = 0;
                                                temp++;
                                                if(temp>5)
                                                {
                                                        temp = 0;
                                                        date_buf[2] = '1';//发送“有小孩”
                                                        CHILD_CHECK_STA = 1;//有小孩
                                                        CHILD_STA = 1;
                                                }
                                        }                                       
                                }
                }       
        }                       
               
/*----------------自动控制模式---------------*/
               
                if(AUTO_CONTORL_STA == 1)//自动控制开
                {
                        OPEN_WIN = 0;
                        CLOSE_WIN = 0;
                        KEY_Scan(0);//扫描是否有按键按下
                        if((OPEN_WIN_STA == 1)&&(CLOSE_WIN_STA == 0))//接收到开窗指令
                        {
                                OPEN_WIN_STA = 0;
                                Motorup = 1;
                                Motordown = 0;                               
                        }
                        if((OPEN_WIN_STA == 0)&&(CLOSE_WIN_STA == 1))//接收到关窗指令
                        {
                                CLOSE_WIN_STA = 0;
                                Motordown = 1;
                                Motorup = 0;
                        }
                        if(RAIN_Flag == 1)//下雨,关窗
                        {
                                RAIN_Flag = 0;
                                OPEN_WIN_STA = 0;
                                CLOSE_WIN_STA = 1;
                                RAIN_temp_Flag = 1;
                        }
                        if(RAIN_AFlag == 1)//雨后开窗
                        {
                                RAIN_AFlag = 0;
                                OPEN_WIN_STA = 1;
                                CLOSE_WIN_STA = 0;
                        }
                        if(CHILD_CHECK_STA == 1)//有小孩,关窗
                        {
                                CHILD_CHECK_STA = 0;
                                OPEN_WIN_STA = 0;
                                CLOSE_WIN_STA = 1;
                                CONTORL_STA = 1;
                        }
               
                }[/mw_shl_code]
第五段程序为串口1和4的数据处理:主要是求距离
[mw_shl_code=c,true]#include "Distance.h"

u8 DISTANCE1_STA = 0;//有人状态,1:有人
u8 DISTANCE2_STA = 0;

u16 Distance_read(u8 head,u8 H_data,u8 L_data,u8 end)
{
        u16 distance;
        if(((head+H_data+L_data)&0xff) == end)
        distance = ((H_data<<8)|L_data)/10;

        return distance;
}
       

void Distance_compare(void)
{
        u16 distance1,distance2;
        distance1=Distance_read(USART_RX_BUF[0],USART_RX_BUF[1],USART_RX_BUF[2],USART_RX_BUF[3]);
        distance2=Distance_read(USART4_RX_BUF[0],USART4_RX_BUF[1],USART4_RX_BUF[2],USART4_RX_BUF[3]);

        if(distance2 <85)//人距窗30CM
        {
                        DISTANCE2_STA = 1;
        }
        else DISTANCE2_STA = 0;
  if(distance1 <50)//人距窗30CM
        {
                        DISTANCE1_STA = 1;
        }
        else DISTANCE1_STA = 0;

}
[/mw_shl_code]

通信时(通信采用50MS发送一次数据,100MS接收一次数据),发现DISTANCE1_STA 和DISTANCE2_STA 的状态并不受串口的数据影响,请教一下各位会是什么情况导致的?

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 04:09

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表