主頁 >  其他 > stm32學習

stm32學習

2020-10-27 23:47:01 其他

通過DHT11溫度測量和NRF24L01無線通信控制電機轉動

  • 一、準備作業
  • 二、發送端
    • DHT11模塊
    • 主函式
  • 三、雙端
    • NRF24L01模塊
    • SPI模塊
  • 四、接收端
    • MOTOR模塊
    • 主函式

一、準備作業

元器件數量
stm32F103C8T62
28BYJ-48步進電機1
uln20031
nrf24l012
dht11模塊1

二、發送端

DHT11模塊

DHT11用來測量溫度

dht11.h

#ifndef __DHT11_H
#define __DHT11_H   
#include "sys.h"
 
//IO方向設定
#define DHT11_IO_IN()  {GPIOB->CRL&=0XFFFFFFF0;GPIOB->CRL|=8<<0;}
#define DHT11_IO_OUT() {GPIOB->CRL&=0XFFFFFFF0;GPIOB->CRL|=3<<0;}
//IO操作函式											   
#define	DHT11_DQ_OUT PBout(0)
#define	DHT11_DQ_IN  PBin(0) 
 
u8 DHT11_Init(void);
u8 DHT11_Read_Data(u8 *temp,u8 *humi);
u8 DHT11_Read_Byte(void);
u8 DHT11_Read_Bit(void);
void DHT11_Rst(void);
u8 DHT11_Check(void);
 
#endif


dht11.c

#include "dht11.h"
#include "delay.h"
 
//初始化DHT11
//回傳:初始化的狀態(應答信號)
u8 DHT11_Init()
{
	GPIO_InitTypeDef GPIO_InitStruce;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);		//利用引腳PA0
	
	GPIO_InitStruce.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStruce.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruce.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStruce);
 
	DHT11_Rst();
	return DHT11_Check();
}
 
//復位DHT11
void DHT11_Rst(void)	   
{                 
    DHT11_IO_OUT(); 	//SET OUTPUT
    DHT11_DQ_OUT=0; 	//拉低DQ
    delay_ms(20);    	//拉低至少18ms
    DHT11_DQ_OUT=1; 	//DQ=1 
    delay_us(30);     	//主機拉高20~40us
}
 
//等待DHT11的回應
//回傳1:未檢測到DHT11的存在
//回傳0:存在
u8 DHT11_Check(void) 	   
{   
   u8 retry=0;
   DHT11_IO_IN();//SET INPUT	 
   while (DHT11_DQ_IN&&retry<100)//DHT11會拉低40~80us
   {
		retry++;   
		delay_us(1);
   };	 
   if(retry>=100)return 1;
   else retry=0;
   while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后會再次拉高40~80us
   {
       retry++;  
	   delay_us(1);
   };
   if(retry>=100)return 1;	    
   return 0;
}
 
//從DHT11讀取一個位   
//回傳值:1/0
u8 DHT11_Read_Bit(void) 			 
{
      u8 retry=0;
      while(DHT11_DQ_IN&&retry<100)//等待變為低電平
      {
             retry++;   
             delay_us(1);
       }
      retry=0;
      while(!DHT11_DQ_IN&&retry<100)//等待變高電平
       {
              retry++;	
              delay_us(1);
         }
      delay_us(40);//等待40us
      if(DHT11_DQ_IN)
		  return 1;
      else 
		  return 0;		   
}
 
//從DHT11讀取一個位元組
//回傳值:讀到的資料
u8 DHT11_Read_Byte(void)    
{        
    u8 i,dat;
    dat=0;
   for (i=0;i<8;i++) 
  {
      dat<<=1; 
     dat|=DHT11_Read_Bit();
    }				    
    return dat;
}
 
//從DHT11讀取一次資料
//temp:溫度值(范圍:0~50°)     humi:濕度值(范圍:20%~90%)
//回傳值:0,正常;1,讀取失敗
u8 DHT11_Read_Data(u8 *temp,u8 *humi)    
{        
    u8 buf[5];
    u8 i;
    DHT11_Rst();
    if(DHT11_Check()==0)
   {
          for(i=0;i<5;i++)//讀取40位資料
		{
			buf[i]=DHT11_Read_Byte();
		}
		if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
		{
			*humi=buf[0];
			*temp=buf[2];
		}
	}else return 1;
	return 0;	    
}

主函式

main.c



#include	"stm32f10x.h"
#include	"system.h"
#include	"delay.h"
#include	"usart.h"
#include	"nrf24l01p.h"	
#include	"spi2.h"
#include  "led.h"
#include  "dht11.h"
#include  "stdio.h"

int main(void)
{
	u8 temperature=0;  	    
	u8 humidity;
	u8 key,mode;
	u8 t=0;			 
	u8 tmp_buf[180];		    
	delay_init();	    	 														//延時函式初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//設定中斷優先級分組為組22位搶占優先級,2位回應優先級
	USART1_Config();	 															//串口初始化為115200
 	NRF24L01_Init();	//初始化NRF24L01
	LED_Init();
	DHT11_Init();
	
	while(DHT11_Init())	//DHT11初始化	
	{
		printf("DHT11 Error\r\n");
		delay_ms(200);
	}
	
	while(NRF24L01_Check())		//等待模塊應答
	{
		printf("NRF24L01 Error\r\n");
		delay_ms(500);
	}
	printf("NRF24L01 OK\r\n");
	
	
	//mode=1;//接收模式
//	mode=1;//發送模式
	
 /*	while(1)
	{
		

		if(mode==0)//RX模式
		{
			printf("NRF24L01 RX_Mode\r\n");
			printf("Received DATA:");
			NRF24L01_RX_Mode();
			while(1)
			{
				if(NRF24L01_RxPacket(tmp_buf)==0)//一旦接收到資訊,則顯示出來.
				{
					tmp_buf[32]=0;//加入字串結束符
					printf("%s\r\n",tmp_buf);
				}
				else delay_us(100);			    
			};
		}
		else//TX模式  */
		
			//printf("NRF24L01 TX_Mode\r\n");
			NRF24L01_TX_Mode();
			//mode=3;//從空格鍵開始
			
		while(1)
		{
			if(NRF24L01_TxPacket(&temperature)==TX_OK)
			{
				if(t%10==0)
				{
					printf("%d",t);
					DHT11_Read_Data(&temperature,&humidity);
					//tmp_buf[t]=temperature;
					printf("Sended DATA:");
					printf("%d\n",temperature);
				}
				delay_ms(10);
				LED0=!LED0;
				  t++;
				  
				
				
				
				
				
				//printf("Sended DATA:");
				//printf("%d\r\n",tmp_buf);
				//printf("%s\r\n",tmp_buf[t]);
				
				//發送的內容(修改發送的內容)
				//key=mode;
				//for(t=0;t<32;t++)
				//{
				//	tmp_buf[t]=key;
				//}
				
				//tmp_buf[0]='0';
				//tmp_buf[1]='0';
				//tmp_buf[2]='0';
				//tmp_buf[3]='0';
				//tmp_buf[4]='0';
				//tmp_buf[5]='5';
				//tmp_buf[6]='6';
				//tmp_buf[7]='7';
				//tmp_buf[8]='8';
				//tmp_buf[9]='9';
				
				//delay_ms(10);
				//tmp_buf[32]=0;//加入結束符
			}
			else
			{										   	
				printf("Send Failed \r\n");
			}
			delay_ms(1500);
		}
	
}
	


三、雙端

NRF24L01模塊

nrf24l01.h

#ifndef __24L01_H
#define __24L01_H	 		  
#include "system.h"
#include "delay.h"
#include "spi2.h"
#include "usart.h"


//NRF24L01暫存器操作命令
#define NRF_READ_REG    0x00  //讀配置暫存器,低5位為暫存器地址
#define NRF_WRITE_REG   0x20  //寫配置暫存器,低5位為暫存器地址
#define RD_RX_PLOAD     0x61  //讀RX有效資料,1~32位元組
#define WR_TX_PLOAD     0xA0  //寫TX有效資料,1~32位元組
#define FLUSH_TX        0xE1  //清除TX FIFO暫存器.發射模式下用
#define FLUSH_RX        0xE2  //清除RX FIFO暫存器.接收模式下用
#define REUSE_TX_PL     0xE3  //重新使用上一包資料,CE為高,資料包被不斷發送.
#define NOP             0xFF  //空操作,可以用來讀狀態暫存器	 
//SPI(NRF24L01)暫存器地址
#define CONFIG          0x00  //配置暫存器地址;bit0:1接收模式,0發射模式;bit1:電選擇;bit2:CRC模式;bit3:CRC使能;
                              //bit4:中斷MAX_RT(達到最大重發次數中斷)使能;bit5:中斷TX_DS使能;bit6:中斷RX_DR使能
#define EN_AA           0x01  //使能自動應答功能  bit0~5,對應通道0~5
#define EN_RXADDR       0x02  //接收地址允許,bit0~5,對應通道0~5
#define SETUP_AW        0x03  //設定地址寬度(所有資料通道):bit1,0:00,3位元組;01,4位元組;02,5位元組;
#define SETUP_RETR      0x04  //建立自動重發;bit3:0,自動重發計數器;bit7:4,自動重發延時 250*x+86us
#define RF_CH           0x05  //RF通道,bit6:0,作業通道頻率;
#define RF_SETUP        0x06  //RF暫存器;bit3:傳輸速率(0:1Mbps,1:2Mbps);bit2:1,發射功率;bit0:低噪聲放大器增益
#define STATUS          0x07  //狀態暫存器;bit0:TX FIFO滿標志;bit3:1,接收資料通道號(最大:6);bit4,達到最多次重發
                              //bit5:資料發送完成中斷;bit6:接收資料中斷;
#define MAX_TX  				0x10  //達到最大發送次數中斷
#define TX_OK   				0x20  //TX發送完成中斷
#define RX_OK   				0x40  //接收到資料中斷

#define OBSERVE_TX      0x08  //發送檢測暫存器,bit7:4,資料包丟失計數器;bit3:0,重發計數器
#define CD              0x09  //載波檢測暫存器,bit0,載波檢測;
#define RX_ADDR_P0      0x0A  //資料通道0接收地址,最大長度5個位元組,低位元組在前
#define RX_ADDR_P1      0x0B  //資料通道1接收地址,最大長度5個位元組,低位元組在前
#define RX_ADDR_P2      0x0C  //資料通道2接收地址,最低位元組可設定,高位元組,必須同RX_ADDR_P1[39:8]相等;
#define RX_ADDR_P3      0x0D  //資料通道3接收地址,最低位元組可設定,高位元組,必須同RX_ADDR_P1[39:8]相等;
#define RX_ADDR_P4      0x0E  //資料通道4接收地址,最低位元組可設定,高位元組,必須同RX_ADDR_P1[39:8]相等;
#define RX_ADDR_P5      0x0F  //資料通道5接收地址,最低位元組可設定,高位元組,必須同RX_ADDR_P1[39:8]相等;
#define TX_ADDR         0x10  //發送地址(低位元組在前),ShockBurstTM模式下,RX_ADDR_P0與此地址相等
#define RX_PW_P0        0x11  //接收資料通道0有效資料寬度(1~32位元組),設定為0則非法
#define RX_PW_P1        0x12  //接收資料通道1有效資料寬度(1~32位元組),設定為0則非法
#define RX_PW_P2        0x13  //接收資料通道2有效資料寬度(1~32位元組),設定為0則非法
#define RX_PW_P3        0x14  //接收資料通道3有效資料寬度(1~32位元組),設定為0則非法
#define RX_PW_P4        0x15  //接收資料通道4有效資料寬度(1~32位元組),設定為0則非法
#define RX_PW_P5        0x16  //接收資料通道5有效資料寬度(1~32位元組),設定為0則非法
#define NRF_FIFO_STATUS 0x17  //FIFO狀態暫存器;bit0,RX FIFO暫存器空標志;bit1,RX FIFO滿標志;bit2,3,保留
                              //bit4,TX FIFO空標志;bit5,TX FIFO滿標志;bit6,1,回圈發送上一資料包.0,不回圈;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//24L01操作線
#define NRF24L01_CE   PAout(7) //24L01片選信號
#define NRF24L01_CSN  PAout(6) //SPI片選信號	   
#define NRF24L01_IRQ  PAin(5)  //IRQ主機資料輸入
//24L01發送接收資料寬度定義
#define TX_ADR_WIDTH    5   	//5位元組的地址寬度
#define RX_ADR_WIDTH    5   	//5位元組的地址寬度
#define TX_PLOAD_WIDTH  32  	//32位元組的用戶資料寬度
#define RX_PLOAD_WIDTH  32  	//32位元組的用戶資料寬度
									   	   

void NRF24L01_Init(void);						//初始化
void NRF24L01_RX_Mode(void);					//配置為接收模式
void NRF24L01_TX_Mode(void);					//配置為發送模式
u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 u8s);//寫資料區
u8 NRF24L01_Read_Buf(u8 reg, u8 *pBuf, u8 u8s);	//讀資料區		  
u8 NRF24L01_Read_Reg(u8 reg);					//讀暫存器
u8 NRF24L01_Write_Reg(u8 reg, u8 value);		//寫暫存器
u8 NRF24L01_Check(void);						//檢查24L01是否存在
u8 NRF24L01_TxPacket(u8 *txbuf);				//發送一個包的資料
u8 NRF24L01_RxPacket(u8 *rxbuf);				//接收一個包的資料
#endif


nrf24l01.c

#include "nrf24l01p.h"

    
const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //發送地址
const u8 RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01};


//初始化24L01的IO口
void NRF24L01_Init(void)
{ 	
	GPIO_InitTypeDef GPIO_InitStructure;
  SPI_InitTypeDef  SPI_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);	 //使能PB,G埠時鐘
	
	//5:IRQ 6:CSN 7:CE
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;	//PA6 7 推挽
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽輸出
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化指定IO
  
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_5;   
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA7 輸入  
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_ResetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);//PA5,6,7上拉
	
  SPI2_Init();    		//初始化SPI	 
 
	SPI_Cmd(SPI2, DISABLE); // SPI外設不使能

	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //SPI設定為雙線雙向全雙工
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;												//SPI主機
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;										//發送接收8位幀結構
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;													//時鐘懸空低
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;												//資料捕獲于第1個時鐘沿
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;														//NSS信號由軟體控制
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;	//定義波特率預分頻的值:波特率預分頻值為16
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;									//資料傳輸從MSB位開始
	SPI_InitStructure.SPI_CRCPolynomial = 7;														//CRC值計算的多項式
	SPI_Init(SPI2, &SPI_InitStructure);																	//根據SPI_InitStruct中指定的引數初始化外設SPIx暫存器
	
	SPI_Cmd(SPI2, ENABLE); //使能SPI外設
			 
	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;
	SPI2_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[i]!=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 =SPI2_ReadWriteByte(reg);//發送暫存器號 
  	SPI2_ReadWriteByte(value);      //寫入暫存器的值
  	NRF24L01_CSN=1;                 //禁止SPI傳輸	   
  	return(status);       			//回傳狀態值
}


//讀取SPI暫存器值
//reg:要讀的暫存器
u8 NRF24L01_Read_Reg(u8 reg)
{
	u8 reg_val;	    
 	NRF24L01_CSN = 0;          //使能SPI傳輸		
  	SPI2_ReadWriteByte(reg);   //發送暫存器號
  	reg_val=SPI2_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=SPI2_ReadWriteByte(reg);//發送暫存器值(位置),并讀取狀態值   	   
 	for(u8_ctr=0;u8_ctr<len;u8_ctr++)
	pBuf[u8_ctr]=SPI2_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 = SPI2_ReadWriteByte(reg);//發送暫存器值(位置),并讀取狀態值
	for(u8_ctr=0; u8_ctr<len; u8_ctr++)SPI2_ReadWriteByte(*pBuf++); //寫入資料	 
	NRF24L01_CSN = 1;       //關閉SPI傳輸
	return status;          //回傳讀到的狀態值
}


//啟動NRF24L01發送一次資料
//txbuf:待發送資料首地址
//回傳值:發送完成狀況
u8 NRF24L01_TxPacket(u8 *txbuf)
{
	u8 sta;
 	SPI2_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);//等待發送完成
	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,接收完成;其他,錯誤代碼
u8 NRF24L01_RxPacket(u8 *rxbuf)
{
	u8 sta;		    							   
	SPI2_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暫存器 
		return 0; 
	}	   
	return 1;//沒收到任何資料
}


//該函式初始化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);//配置基本作業模式的引數;PWR_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);    //配置基本作業模式的引數;PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啟所有中斷
	NRF24L01_CE=1;//CE為高,10us后啟動發送
}





SPI模塊

spi.h

#ifndef __SPI2_H
#define __SPI2_H
#include "stm32f10x.h"

	  	    													  
void SPI2_Init(void);			 //初始化SPI口
void SPI2_SetSpeed(u8 SpeedSet); //設定SPI速度   
u8 SPI2_ReadWriteByte(u8 TxData);//SPI總線讀寫一個位元組
		 
#endif


spi.c

#include "spi2.h"

//以下是SPI模塊的初始化代碼,配置成主機模式,訪問SD Card/W25Q64/NRF24L01						  
//SPI口初始化
//這里針是對SPI2的初始化



void SPI2_Init(void)
{
 	GPIO_InitTypeDef GPIO_InitStructure;
  SPI_InitTypeDef  SPI_InitStructure;

	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );//PORTB時鐘使能 
	RCC_APB1PeriphClockCmd(	RCC_APB1Periph_SPI2,  ENABLE );//SPI2時鐘使能 	
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PB13/14/15復用推挽輸出	13:sck 14:miso 15mosi
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB

 	GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);  //PB13/14/15上拉

	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_High;		//串行同步時鐘的空閑狀態為高電平
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;	//串行同步時鐘的第二個跳變沿(上升或下降)資料被采樣
	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(SPI2, &SPI_InitStructure);  //根據SPI_InitStruct中指定的引數初始化外設SPIx暫存器
 
	SPI_Cmd(SPI2, ENABLE); //使能SPI外設
	
	SPI2_ReadWriteByte(0xff);//啟動傳輸
}   
//SPI 速度設定函式
//SpeedSet:
//SPI_BaudRatePrescaler_2   2分頻   
//SPI_BaudRatePrescaler_8   8分頻   
//SPI_BaudRatePrescaler_16  16分頻  
//SPI_BaudRatePrescaler_256 256分頻 
  
void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler)
{
  	assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
	SPI2->CR1&=0XFFC7;
	SPI2->CR1|=SPI_BaudRatePrescaler;	//設定SPI2速度 
	SPI_Cmd(SPI2,ENABLE); 

} 

//SPIx 讀寫一個位元組
//TxData:要寫入的位元組
//回傳值:讀取到的位元組
u8 SPI2_ReadWriteByte(u8 TxData)
{		
	u8 retry=0;				 	
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //檢查指定的SPI標志位設定與否:發送快取空標志位
	{
		retry++;
		if(retry>200)return 0;
	}			  
	SPI_I2S_SendData(SPI2, TxData); //通過外設SPIx發送一個資料
	retry=0;

	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)//檢查指定的SPI標志位設定與否:接受快取非空標志位
	{
		retry++;
		if(retry>200)return 0;
	}	  						    
	return SPI_I2S_ReceiveData(SPI2); //回傳通過SPIx最近接收的資料					    
}




四、接收端

MOTOR模塊

motor.h

#ifndef __MOTOR_H
#define __MOTOR_H	 
#include "sys.h"
#include <stdbool.h>

//ULN2003驅動

#define uint unsigned int
#define uchar unsigned char

void Delay_xms(uint x);//延時函式
void Moto_Init(void);  //步進電機初始化
void Motorcw(void);    //步進電機正轉函式
void Motorcw1(int speed);   //步進電機1正轉函式
void Motorccw(void);   //步進電機反轉函式
void Motorccw1(int speed);  //步進電機1反轉函式
void Motorcw_angle(int angle,int speed);  //步進電機正轉角度函式
void Motorcw_angle1(int angle,int speed); //步進電機1正轉角度函式
void Motorccw_angle(int angle,int speed); //步進電機反轉角度函式
void Motorccw_angle1(int angle,int speed);//步進電機1反轉角度函式
void MotorStop(void);  //步進電機停止函式
void MotorStop1(void); //步進電機1停止函式
void SetMotor(unsigned char InputData);
//void motorNcircle(int n,bool position);
void motorNcircle(int position);

#endif

motor.c

#include "delay.h"
#include "sys.h"
#include "stdio.h"
#include "motor.h"


unsigned short phasecw[4] ={0x0200,0x0100,0x0080,0x0040};// D-C-B-A   反轉
unsigned short phaseccw[4]={0x0040,0x0080,0x0100,0x0200};// A-B-C-D   正轉

//引腳初始化
void Moto_Init(void)
{
	 GPIO_InitTypeDef GPIO_InitStructure;
	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	 GPIO_Init(GPIOB,&GPIO_InitStructure);
	 GPIO_ResetBits(GPIOB,GPIO_Pin_6 | GPIO_Pin_7 |GPIO_Pin_8 |GPIO_Pin_9 );
}
void MotoRcw(void)  //反轉
{  
    int  i;  
  
    for(i=0;i<4;i++)  
    {  
        GPIO_Write(GPIOB,phasecw[i]);  
        delay_ms(4);  
    }  
}

void MotoRccw(void)  //正轉
{  
    int i;  
    for(i=0;i<4;i++)  
    {  
        GPIO_Write(GPIOB,phaseccw[i]);  
        delay_ms(4);  
    }  
}

void MotorStop(void) //停止
{  
    GPIO_Write(GPIOB,0x0000);  
}

//控制電機正轉還是反轉某個角度
//direction方向,1為正轉,0為反轉
//angle角度,可為0-360具有實際意義
void Motor_Ctrl_Direction_Angle(int direction, int angle)
{
	u16 j;
	if(direction == 1)
	{
		for(j=0;j<64*angle/45;j++) 
		{
			MotoRccw();//正轉
		}
		 MotorStop();//停止
  }
	else
	{
		for(j=0;j<64*angle/45;j++) 
		{
			MotoRcw();//反轉
		}
		 MotorStop();//停止
	}
	
}

主函式

mian.c



#include	"stm32f10x.h"
#include	"system.h"
#include	"delay.h"
#include	"usart.h"
#include	"nrf24l01p.h"	
#include	"spi2.h"
#include  "led.h"
#include  "motor.h"



int main(void)
{
	int flag=1;
	u8 temperature=0;
	u8 key,mode;
	u16 t=0;			 
	u8 tmp_buf[180];		    
	delay_init();	    	 														//延時函式初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//設定中斷優先級分組為組22位搶占優先級,2位回應優先級
	USART1_Config();	 															//串口初始化為115200
 	NRF24L01_Init();    														//初始化NRF24L01 
	Moto_Init();
	LED_Init();
	//delay_ms(1000);
	
	
	
	while(NRF24L01_Check())		//等待模塊應答
	{
		printf("NRF24L01 Error\r\n");
		delay_ms(500);
	}
	printf("NRF24L01 OK\r\n");
	
	
	mode=0;//接收模式
//	mode=1;//發送模式
	
 	while(1)
	{
		

		if(mode==0)//RX模式
		{
			printf("NRF24L01 RX_Mode\r\n");
			printf("Received DATA:");
			NRF24L01_RX_Mode();
			while(1)
			{
				if(NRF24L01_RxPacket(&temperature)==0)//一旦接收到資訊,則顯示出來.
				{
					printf("%d\r\n",temperature);
					LED0=!LED0;
					if(temperature>25&&flag==1)
					{
					Motor_Ctrl_Direction_Angle(1,645);
						flag=0;
						
					}
					//tmp_buf[179]=0;//加入字串結束符
					
					//delay_ms(10);
				}
				else delay_us(100);			    
			}
		}
}
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/194359.html

標籤:其他

上一篇:【論文閱讀】22-GMS: Grid-based Motion Statistics for Fast, Ultra-robust Feature Correspondence

下一篇:264【畢設課設】基于51單片機的速度檢測系統設計-霍爾

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more