通過DHT11溫度測量和NRF24L01無線通信控制電機轉動
- 一、準備作業
- 二、發送端
- DHT11模塊
- 主函式
- 三、雙端
- NRF24L01模塊
- SPI模塊
- 四、接收端
- MOTOR模塊
- 主函式
一、準備作業
| 元器件 | 數量 |
|---|---|
| stm32F103C8T6 | 2 |
| 28BYJ-48步進電機 | 1 |
| uln2003 | 1 |
| nrf24l01 | 2 |
| 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); //設定中斷優先級分組為組2:2位搶占優先級,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); //設定中斷優先級分組為組2:2位搶占優先級,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
