stm32f103c8t6最小系统板+nrf24l01制作简易船模
前言:
? ? 大二興趣使然參加了學校的船模設計比賽,也算是第一次正式比賽的經驗,一番努力下來也算是有所收獲,雖說現在船已經不在身邊,但還是想憑著記憶把制作過程捋一遍,就當是記錄學習過程吧(該文章僅供參考,相信各位看我文章只圖一樂,真做起來當然會比我初出茅廬做得好啦)
非保姆級非保姆級非保姆級,細節處需要思考,謝謝
設計思路:
可以看見所需理解并使用的功能有:adc采集、pwm輸出、nrf24l01通信?,這些功能的使用在本站有大把文章講述,故不作過多闡述,學習后再參考本文即可。
軟件實現:
本文章大部分使用正點原子例程修改。
main.c
#include "system.h" #include "SysTick.h" #include "led.h" #include "usart.h" #include "nrf24l01.h" #include "string.h" #include "adc.h" #include<stdio.h> #include "pwm.h"int main() {//u8 mode=0; u8 mode=1;int val1=0,val2=0;long int adc=0;u8 rx_buf[33]="123456"; SysTick_Init(72);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中斷優先級分組 分2組.0USART1_Init(9600);NRF24L01_Init();ADCx_Init();TIM1_PWM_Init(9999,143);TIM3_CH1_PWM_Init(199,7199);//20msprintf("2.4G Telecontrol\r\n");while(NRF24L01_Check()) //檢測NRF24L01是否存在{printf("2G4 ERROR\r\n"); }printf("2G4 OK\r\n");if(mode==1)//發送模式{NRF24L01_TX_Mode();//先設置為發送函數while(1){val1=Get_ADC1_Value(ADC_Channel_0,20);val2=Get_ADC1_Value(ADC_Channel_1,20);//獲取adc值printf("檢測AD1值為:%d\r\n",val1);//串口檢驗printf("檢測AD2值為:%d\r\n",val2);if(1500<=val1&&val1<=2000)//分檔val1=9210;else if(1000<=val1&&val1<1500)val1=9190;else if(500<=val1&&val1<1000)val1=9180;else if(0<=val1&&val1<=500)val1=9165;elseval1=9220;if(1600<val2&&val2<2500)val2=15;else if(val2<=1600)val2=5;else if(val2>=2500)val2=25;printf("電機數字為:%d\r\n",val1);printf("舵機數字為:%d\r\n",val2);adc=val1*100+val2;sprintf(rx_buf,"%d",adc);NRF24L01_TxPacket(rx_buf);}}if(mode==0)//接收模式{TIM_SetCompare1(TIM1,9000);delay_ms(50);TIM_SetCompare1(TIM1,9220);delay_ms(50);NRF24L01_RX_Mode(); while(1){if(NRF24L01_RxPacket(rx_buf)==0) //接收到數據顯示{long int adc1=9220,adc2=15 ;rx_buf[32]='\0';sscanf(rx_buf,"%4d",&adc1);sscanf(rx_buf,"%d",&adc2);adc2=adc2-adc1*100;printf("電機數字為:%d\r\n",adc1);printf("舵機數字為:%d\r\n",adc2);TIM_SetCompare1(TIM1,adc1);//設置占空比TIM_SetCompare1(TIM3,adc2);} }}return 0; }nrf24l01.c
#include "nrf24l01.h" #include "spi.h" #include "usart.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;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 使能PB端口時鐘/*GPIO_Mode_Out_PP是作為普通IO口,在NRF2401上是CS片選信號和IRQ模塊的中斷信號*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_12; // PB10、PB12推挽 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 作為普通IO推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); // 初始化指定IOGPIO_ResetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_12); // PB10、PB12輸出低//為低的話實際是使能片選,但是因為C8T6上面沒有W25Q128,所以使能沒問題/*這個應該是CE、使能芯片的接發模式*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // PB11輸入 GPIO_Init(GPIOB, &GPIO_InitStructure);SPI2_Init_JX(); // 初始化SPI NRF24L01_CE=0; //使能24L01NRF24L01_CSN=1; //SPI片選取消 }//檢測24L01是否存在 //返回值:0,成功;1,失敗 u8 NRF24L01_Check(void) {u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};u8 i;SPI2_SetSpeed(SPI_BaudRatePrescaler_4); //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/*for(i=0;i<5;i++){if(buf[i]!=0XA5){return 1;break;}}*/}//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);//發送寄存器值(位置),并讀取狀態值//printf("%d",status);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_4);//spi速度為9Mhz(24L01的最大SPI時鐘為10Mhz) NRF24L01_CE=0;//開啟2.4G的傳輸--------------下面有配套的NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//寫數據到TX BUF 32個字節 ****NRF24L01_Write_Buf(),寫函數 //里面協議有開啟spi的傳輸 NRF24L01_CSN=0NRF24L01_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,60); //設置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,60); //設置RF通道為60NRF24L01_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.c
#include "spi.h"// SPI2初始化 //--------------------------------------------------------------------------------------------------------------- void SPI2_Init_JX(void) {GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef SPI_InitStructure;RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); // GPIOB時鐘使能 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復用推挽輸出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure); // 初始化GPIOBGPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); // PB13/14/15上拉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; // 定義波特率預分頻的值:波特率預分頻值為16SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 數據傳輸從MSB位開始SPI_InitStructure.SPI_CRCPolynomial = 7; // CRC值計算的多項式SPI_Init(SPI2, &SPI_InitStructure);SPI_Cmd(SPI2, ENABLE); // 使能SPI外設SPI2_ReadWriteByte(0xFF); // 啟動傳輸 } //---------------------------------------------------------------------------------------------------------------// 設置SPI速度 //--------------------------------------------------- // SPI_DivideFrequency_2 2分頻: 18MHz // SPI_DivideFrequency_4 4分頻: 9MHz // SPI_DivideFrequency_8 8分頻: 4.5MHz // SPI_DivideFrequency_16 16分頻:2.25MHz void SPI2_SetSpeed(u8 SPI_DivideFrequency) {SPI2->CR1&=0XFFC7;SPI2->CR1|=SPI_DivideFrequency; //設置SPI2速度 //SPI_Cmd(SPI2,ENABLE); } //---------------------------------------------------// SPI讀寫一個字節 // TxData:要寫入的字節 // 返回值:讀取到的字節 //----------------------------------------------------------------------- u8 SPI2_ReadWriteByte(u8 TxData) { u8 TxWait = 0;u8 RxWait = 0;// 等待發送緩存為空while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET){TxWait++;if(TxWait>250) // 等待時間過長則放棄本次讀寫return 0;} SPI_I2S_SendData(SPI2, TxData); // SPI2寫一個字節// 等待接收緩存為空while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET){RxWait++;if(RxWait>250) // 等待時間過長則放棄本次讀寫return 0;} return SPI_I2S_ReceiveData(SPI2); // 將讀到的字節返回 } //-----------------------------------------------------------------------adc.c
#include "adc.h" #include "SysTick.h"void ADCx_Init() {GPIO_InitTypeDef GPIO_InitStructure;//定義結構體變量ADC_InitTypeDef ADC_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);RCC_ADCCLKConfig(RCC_PCLK2_Div6);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1; //選擇你要設置的IO口GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //設置傳輸速率,輸入可不要GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */ADC_DeInit(ADC1); //復位ADC1,將外設 ADC1 的全部寄存器重設為缺省值ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;ADC_InitStructure.ADC_ScanConvMode=ENABLE;//掃描模式ADC_InitStructure.ADC_ContinuousConvMode=ENABLE;//連續觸發ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;//外部觸發禁用ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//數據對齊方式ADC_InitStructure.ADC_NbrOfChannel=2;//通道數ADC_Init(ADC1,&ADC_InitStructure);// ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_239Cycles5); // ADC_RegularChannelConfig(ADC1,ADC_Channel_1,2,ADC_SampleTime_239Cycles5);ADC_Cmd(ADC1,ENABLE);ADC_ResetCalibration(ADC1);//復位校準寄存器while(ADC_GetResetCalibrationStatus(ADC1));ADC_StartCalibration(ADC1);//開始校準while(ADC_GetCalibrationStatus(ADC1));ADC_SoftwareStartConvCmd(ADC1,ENABLE);//軟件觸發 }u16 Get_ADC1_Value(u8 ch,u8 times)//通道,采集次數 {u8 t;u32 temp_val1=0,temp_val2=0;ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_239Cycles5);//設置規則通道ADC_RegularChannelConfig(ADC1,ch,2,ADC_SampleTime_239Cycles5);//設置規則通道for(t=0;t<times;t++)//多次采集{ADC_SoftwareStartConvCmd(ADC1,ENABLE);//軟件觸發while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//返回為1,轉化完成if(0<=t&&t<=3)ADC_GetConversionValue(ADC1);if(t>3&&t%2==0)temp_val1+=ADC_GetConversionValue(ADC1);if(t>3&&t%2==1)temp_val2+=ADC_GetConversionValue(ADC1);delay_ms(5);}if(ch==ADC_Channel_0)return temp_val1*2/(times-4);if(ch==ADC_Channel_1)return temp_val2*2/(times-4); }u16 Get_ADC2_Value(u8 ch,u8 times)//通道,采集次數 {u8 t;u32 temp_val=0;ADC_RegularChannelConfig(ADC1,ch,2,ADC_SampleTime_239Cycles5);//設置規則通道for(t=0;t<times;t++)//多次采集{ADC_SoftwareStartConvCmd(ADC1,ENABLE);//軟件觸發while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//返回為1,轉化完成if(t%2==1)temp_val+=ADC_GetConversionValue(ADC1);delay_ms(5);}return temp_val/times; }pwm.c
#include "pwm.h" #include "led.h" // //本程序只供學習使用,未經作者許可,不得用于其它任何用途 //ALIENTEK Mini STM32開發板 //PWM 驅動代碼 //正點原子@ALIENTEK //技術論壇:www.openedv.com //修改日期:2010/12/03 //版本:V1.0 //版權所有,盜版必究。 //Copyright(C) 正點原子 2009-2019 //All rights reserved // //PWM輸出初始化 //arr:自動重裝值 //psc:時鐘預分頻數 void TIM1_PWM_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能GPIO外設時鐘使能//設置該引腳為復用輸出功能,輸出TIM1 CH1的PWM脈沖波形GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM_CH1GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復用推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);TIM_TimeBaseStructure.TIM_Period = arr; //設置在下一個更新事件裝入活動的自動重裝載寄存器周期的值 80KTIM_TimeBaseStructure.TIM_Prescaler =psc; //設置用來作為TIMx時鐘頻率除數的預分頻值 不分頻TIM_TimeBaseStructure.TIM_ClockDivision = 0; //設置時鐘分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根據TIM_TimeBaseInitStruct中指定的參數初始化TIMx的時間基數單位TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //選擇定時器模式:TIM脈沖寬度調制模式2TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比較輸出使能TIM_OCInitStructure.TIM_Pulse = 0; //設置待裝入捕獲比較寄存器的脈沖值TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出極性:TIM輸出比較極性高TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根據TIM_OCInitStruct中指定的參數初始化外設TIMxTIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主輸出使能 TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1預裝載使能 TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的預裝載寄存器TIM_Cmd(TIM1, ENABLE); //使能TIM1}void TIM3_CH1_PWM_Init(u16 pre,u16 psc) {GPIO_InitTypeDef GPIO_InitStructure;//定義結構體變量TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_OCInitTypeDef TIM_OCInitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6; //選擇你要設置的IO口GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //設置推挽輸出模式GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //設置傳輸速率GPIO_Init(GPIOA,&GPIO_InitStructure); /* 初始化GPIO */TIM_TimeBaseInitStructure.TIM_Period=pre;//重載TIM_TimeBaseInitStructure.TIM_Prescaler=psc;//預分頻系數TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//1分頻TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;TIM_OC1Init(TIM3,&TIM_OCInitStructure);TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);TIM_ARRPreloadConfig(TIM3,ENABLE);TIM_Cmd(TIM3,ENABLE); }硬件實現:
遙控器原理圖:?
船模接收端原理圖:
主要零件選擇:
以及:船殼一套(我買的是西南科普模型的套材,需要自己組裝、空間分配),stm32f103c8t6最小系統板 x 2、nrf24l01 x 2、杜邦線若干、搖桿(電位器)x 2、遙控供電模塊 x 1、環氧樹脂一瓶、拉桿x1、螺旋槳x1、軸總成x1、風琴套x1、ab膠若干。
?(此為船模比賽中選用部件,在淘寶店鋪模型風向標可購買,實際使用中2835電機馬力遠遠超出所需,可采用馬力更小的電機。)
?實物圖:(只有這么多了,平常不愛拍照 = = )
?
船模效果預覽:
鏈接:https://pan.baidu.com/s/1ClJqUcCQa1HZsOu5ee1Jug?pwd=e5in?
提取碼:e5in
開起來還是很帶勁的!
全套源碼:stm32f103c8t6+nrf24l01船模設計比賽項目源碼-單片機文檔類資源-CSDN下載
總結
以上是生活随笔為你收集整理的stm32f103c8t6最小系统板+nrf24l01制作简易船模的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最美洗脚妹”刘丽感动中国
- 下一篇: AutoView自动为旧设计稿更新新设计