初级会员
- 积分
- 84
- 金钱
- 84
- 注册时间
- 2016-12-27
- 在线时间
- 14 小时
|
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 的状态并不受串口的数据影响,请教一下各位会是什么情况导致的?
|
|