在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > STM32 驅動無線NRF24L01 完成串口數(shù)據(jù)傳輸

            STM32 驅動無線NRF24L01 完成串口數(shù)據(jù)傳輸

            作者: 時間:2016-12-03 來源:網(wǎng)絡 收藏
            2401 一個簡單的SPI 接口的 2.4G 射頻模塊 淘寶價20¥,DIY 的17¥ ,算是廉價。
            這個版本的穩(wěn)定修正http://ntn314.blog.163.com/blog/static/16174358420106211118944/
            接口CMOS電平3.3V STM32 可直接連接。接受完成 發(fā)送完成 出錯 都有IRQ 低電平中斷產(chǎn)生。程序中 我將其連接至一IO口在外部中斷中處里各類事件 但也發(fā)現(xiàn)這種處理方式并不是特別靈活,或許直接判斷更加靈活。
            NRF20L01一次可以傳輸 1~32個字節(jié)比較靈活。最初我是根據(jù)字符串長來不停的轉換每次傳輸?shù)拈L度,這樣做十分麻煩最后用截取有效串長的方法實現(xiàn)效果很好。
            程序修修改過 總算穩(wěn)定了 不過在傳輸大于32個字節(jié)的信息時出錯的概率很大,原因暫時不清楚,不過能自動恢復過來。另外在帶有硬件的在線仿真調試的時候一定要運行前斷開外部硬件的電源再重新連接,保證外部器件的正常初始化。
            /***********************s****************************/
            u8 tran=0; //中斷標志
            u8 sta; //定義一個可位尋址的變量sta
            uc8 TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};
            char RX_BUF[256];
            uchar TX_BUF[256];

            /**************************************************/
            void RF_SPI_Config(void)
            {
            SPI_InitTypeDef SPI_InitStructure;
            GPIO_InitTypeDef GPIO_InitStructure;
            EXTI_InitTypeDef EXTI_InitStructure;
            RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);

            /* PB15-MOSI2,PB13-SCK2*/
            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 |GPIO_Pin_14 | GPIO_Pin_15;
            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
            GPIO_Init(GPIOB, &GPIO_InitStructure);
            //IRQ
            GPIO_SetBits(GPIOB, GPIO_Pin_0);
            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
            GPIO_Init(GPIOB, &GPIO_InitStructure);
            GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
            /* 配置中斷線0為下降觸發(fā)*/
            EXTI_InitStructure.EXTI_Line = EXTI_Line0;
            EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
            EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
            EXTI_InitStructure.EXTI_LineCmd = ENABLE;
            EXTI_Init(&EXTI_InitStructure);
            /*PB2-CS*/
            GPIO_SetBits(GPIOB, GPIO_Pin_2);//預置為高
            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
            GPIO_Init(GPIOB, &GPIO_InitStructure);
            /*PC4-A0*/
            GPIO_SetBits(GPIOC, GPIO_Pin_4);//預置為高
            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
            GPIO_Init(GPIOC, &GPIO_InitStructure);
            /*LED*/
            GPIO_SetBits(GPIOB, GPIO_Pin_12);//預置為高
            GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
            GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
            GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
            GPIO_Init(GPIOB, &GPIO_InitStructure);
            /* SPI2 configuration */
            SPI_Cmd(SPI2, DISABLE); //必須先禁能,才能改變MODE
            SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//兩線全雙工
            SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//主
            SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//8位
            SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;//CPOL=0 時鐘懸空低
            SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;//CPHA=0 數(shù)據(jù)捕獲第1個
            SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;//軟件NSS
            SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64 ;//64分頻
            SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;//高位在前
            SPI_InitStructure.SPI_CRCPolynomial = 7;//CRC7

            SPI_Init(SPI2, &SPI_InitStructure);
            SPI_Cmd(SPI2, ENABLE);
            }
            /**************************************************************
            但切記不可忽略SPI的硬件接收,因為讀SPI_DR才能清除RXEN
            ***************************************************************/
            u8 SPI_RW(u8 byte)
            {
            /*等待發(fā)送寄存器空*/
            while((SPI2->SR & SPI_I2S_FLAG_TXE)==RESET);
            /*發(fā)送一個字節(jié)*/
            SPI2->DR = byte;
            /* 等待接收寄存器有效*/
            while((SPI2->SR & SPI_I2S_FLAG_RXNE)==RESET);
            return(SPI2->DR);
            }
            /**************************************************
            函數(shù):SPI_RW_Reg()
            描述:寫數(shù)據(jù)value到reg寄存器
            *************************************************/
            u8 SPI_RW_Reg(u8 reg, u8 value)
            {
            u8 status;
            CSN_L; // CSN置低,開始傳輸數(shù)據(jù)
            status = SPI_RW(reg); // 選擇寄存器,同時返回狀態(tài)字
            SPI_RW(value); // 然后寫數(shù)據(jù)到該寄存器
            CSN_H; // CSN拉高,結束數(shù)據(jù)傳輸
            return(status); // 返回狀態(tài)寄存器
            }
            /**************************************************
            函數(shù): init_io()
            描述:初始化IO
            *************************************************/
            void RX_Mode(void);
            void init_io(void)
            {
            CE_L; // 待機
            CSN_H; // SPI禁止
            LED1;// 關閉指示燈
            RX_Mode();//接收
            }
            /**************************************************
            函數(shù):SPI_Read()
            描述:從reg寄存器讀一字節(jié)
            *************************************************/
            u8 SPI_Read(u8 reg)
            {
            u8 reg_val;
            CSN_L; // CSN置低,開始傳輸數(shù)據(jù)
            SPI_RW(reg); // 選擇寄存器
            reg_val = SPI_RW(0); // 然后從該寄存器讀數(shù)據(jù)
            CSN_H; // CSN拉高,結束數(shù)據(jù)傳輸
            return(reg_val); // 返回寄存器數(shù)據(jù)
            }
            /**************************************************
            函數(shù):SPI_Read_Buf()
            描述:從reg寄存器讀出bytes個字節(jié),通常用來讀取接收通道
            數(shù)據(jù)或接收/發(fā)送地址
            *************************************************/
            uchar SPI_Read_Buf(uchar reg, char * pBuf, uchar bytes)
            {
            uchar status, i;
            CSN_L; // CSN置低,開始傳輸數(shù)據(jù)
            status = SPI_RW(reg); // 選擇寄存器,同時返回狀態(tài)字
            for(i=0; i pBuf[i] = SPI_RW(0); // 逐個字節(jié)從nRF24L01讀出
            CSN_H; // CSN拉高,結束數(shù)據(jù)傳輸
            return(status); // 返回狀態(tài)寄存器
            }
            /**************************************************
            函數(shù):SPI_Write_Buf()
            描述:把pBuf緩存中的數(shù)據(jù)寫入到nRF24L01,通常用來寫入發(fā)
            射通道數(shù)據(jù)或接收/發(fā)送地址
            *************************************************/
            uchar SPI_Write_Buf(uchar reg, uchar * pBuf, uchar bytes)
            {
            uchar status, i;
            CSN_L; // CSN置低,開始傳輸數(shù)據(jù)
            status = SPI_RW(reg); // 選擇寄存器,同時返回狀態(tài)字
            for(i=0; i SPI_RW(pBuf[i]); // 逐個字節(jié)寫入nRF24L01
            CSN_H; // CSN拉高,結束數(shù)據(jù)傳輸
            return(status); // 返回狀態(tài)寄存器
            }
            /**************************************************
            函數(shù):RX_Mode()
            描述:這個函數(shù)設置nRF24L01為接收模式,等待接收發(fā)送設備的數(shù)據(jù)包
            *************************************************/
            void RX_Mode(void)
            {
            CE_L;
            SPI_Write_Buf(RF_WRITE_REG + RX_ADDR_P0, (u8*)TX_ADDRESS, TX_ADR_WIDTH); // 接收設備接收通道0使用和發(fā)送設備相同的發(fā)送地址
            SPI_RW_Reg(RF_WRITE_REG + EN_AA, 0x01); // 使能接收通道0自動應答
            SPI_RW_Reg(RF_WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0
            SPI_RW_Reg(RF_WRITE_REG + RF_CH, 40); // 選擇射頻通道0x40
            SPI_RW_Reg(RF_WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // 接收通道0選擇和發(fā)送通道相同有效數(shù)據(jù)寬度
            SPI_RW_Reg(RF_WRITE_REG + RF_SETUP, 0x07); // 數(shù)據(jù)傳輸率1Mbps,發(fā)射功率0dBm,低噪聲放大器增益
            SPI_RW_Reg(RF_WRITE_REG + CONFIG, 0x0f); // CRC使能,16位CRC校驗,上電,接收模式
            CE_H; // 拉高CE啟動接收設備
            }
            /**************************************************
            函數(shù):TX_Mode()
            描述:
            這個函數(shù)設置nRF24L01為發(fā)送模式,(CE=1持續(xù)至少10us),
            130us后啟動發(fā)射,數(shù)據(jù)發(fā)送結束后,發(fā)送模塊自動轉入接收
            模式等待應答信號。
            *************************************************/
            void TX_Mode(uchar * BUF)
            {
            CE_L;
            SPI_Write_Buf(RF_WRITE_REG + TX_ADDR, (u8*)TX_ADDRESS, TX_ADR_WIDTH); // 寫入發(fā)送地址
            SPI_Write_Buf(RF_WRITE_REG + RX_ADDR_P0, (u8*)TX_ADDRESS, TX_ADR_WIDTH); // 為了應答接收設備,接收通道0地址和發(fā)送地址相同
            SPI_Write_Buf(WR_TX_PLOAD, BUF, TX_PLOAD_WIDTH); // 寫數(shù)據(jù)包到TX FIFO
            SPI_RW_Reg(RF_WRITE_REG + EN_AA, 0x01); // 使能接收通道0自動應答
            SPI_RW_Reg(RF_WRITE_REG + EN_RXADDR, 0x01); // 使能接收通道0
            SPI_RW_Reg(RF_WRITE_REG + SETUP_RETR, 0x0a); // 自動重發(fā)延時等待250us+86us,自動重發(fā)10次
            SPI_RW_Reg(RF_WRITE_REG + RF_CH, 40); // 選擇射頻通道0x40
            SPI_RW_Reg(RF_WRITE_REG + RF_SETUP, 0x07); // 數(shù)據(jù)傳輸率1Mbps,發(fā)射功率0dBm,低噪聲放大器增益
            SPI_RW_Reg(RF_WRITE_REG + CONFIG, 0x0e); // CRC使能,16位CRC校驗,上電
            CE_H;CE_H;delay_ms(1);
            }
            /**************************************************
            函數(shù):Check_ACK()
            描述:
            檢查接收設備有無接收到數(shù)據(jù)包,設定沒有收到應答信
            號是否重發(fā)
            ***************************************************/
            uchar Check_ACK(u8 clear)
            {
            while(IRQ);
            sta = SPI_RW(NOP); // 返回狀態(tài)寄存器
            if(MAX_RT)
            if(clear) // 是否清除TX FIFO,若沒有清除在清除MAX_RT中斷標志后重發(fā)
            SPI_RW(FLUSH_TX);
            SPI_RW_Reg(RF_WRITE_REG + STATUS, sta); // 清除TX_DS或MAX_RT中斷標志
            IRQ_H;
            if(TX_DS)
            return(0x00);
            else
            return(0xff);
            }

            void sent_data(u8* fp,u16 flong)
            {
            u16 i=65535;
            TX_Mode((u8*)&flong); //傳送長度
            while(!tran&&i>1)i--; //等待完成
            tran=0;
            flong=flong/33+1;
            for(i=0;i<20000;i++);//130uS*2延時
            while(flong)
            {
            if(MAX_RT) return;//無應答返回
            TX_Mode(fp); //傳送數(shù)據(jù)
            while(!tran&&i>1)i--; //等待完成
            tran=0;
            for(i=0;i<20000;i++);//130uS*2延時
            fp+=32;flong--;
            }
            }
            extern u8 RX_NU;
            void test (void)
            {
            if (Uart2_Get_Flag!=0&&Timer2==0)
            {
            sent_data(TX_BUF,(u16)Uart2_Get_Flag);
            Uart2_Get_Flag=0;
            }

            if(Timer2==0&&RX_NU==2)
            {
            RX_NU=1;
            USART2_Puts("傳輸錯誤 ");
            USART2_Puts("rn");
            }
            }
            兩個中斷 串口 和 外部中斷
            /*******************************************************************************
            * Function Name : EXTI0_IRQHandler
            * Description : This function handles External interrupt Line 0 request.
            * Input : None
            * Output : None
            * Return : None
            *******************************************************************************/
            extern u8 sta;
            extern char RX_BUF[256];
            extern uchar TX_BUF[256];
            extern u8 SPI_RW_Reg(u8 reg, u8 value);
            extern void RX_Mode(void);
            extern uchar SPI_Read_Buf(uchar reg, char * pBuf, uchar bytes);
            u8 RX_NU=1;//1接收長度 2接收數(shù)據(jù)
            u16 rectnu,onerc; //接收串長,接收次數(shù)
            char* PRX_BUF=RX_BUF;
            void EXTI0_IRQHandler(void)
            {
            EXTI_ClearITPendingBit(EXTI_Line0);
            tran=1;
            CSN_L;
            sta=SPI_RW(NOP); // 返回狀態(tài)寄存器
            CSN_H;

            if(MAX_RT)
            {
            USART2_Puts("對方無應答 ");
            CSN_L;
            SPI_RW(FLUSH_TX); // 清除TX FIFO,若沒有清除在清除MAX_RT中斷標志后重發(fā)
            CSN_H;
            SPI_RW_Reg(RF_WRITE_REG + STATUS, sta);
            }

            if(TX_DS)
            {
            SPI_RW_Reg(RF_WRITE_REG + STATUS, sta); // 清除TX_DS或MAX_RT中斷標志
            }
            if(RX_DR) // 判斷是否接受到數(shù)據(jù)
            {

            if(RX_NU==1)
            {
            CE_L;
            SPI_Read_Buf(RD_RX_PLOAD, RX_BUF, TX_PLOAD_WIDTH); // 從RX FIFO讀出數(shù)據(jù)
            SPI_RW_Reg(RF_WRITE_REG + STATUS, sta); // 清除RX_DS中斷標志
            rectnu=RX_BUF[0];rectnu|=RX_BUF[1]<<8; //接收串長
            onerc=rectnu/33+1; //計算接收次數(shù)
            RX_NU=2;RX_Mode();Timer2=500;/*超時時間*/
            return;
            }
            if(RX_NU==2)
            {
            CE_L;
            SPI_Read_Buf(RD_RX_PLOAD, PRX_BUF, TX_PLOAD_WIDTH); // 從RX FIFO讀出數(shù)據(jù)
            SPI_RW_Reg(RF_WRITE_REG + STATUS, sta); // 清除RX_DS中斷標志
            onerc--;PRX_BUF+=32; //接收計數(shù) 接收指針移動
            if(!onerc)
            {
            RX_BUF[rectnu]=