前言:
大二兴趣使然参加了学校的船模设计比赛,也算是第一次正式比赛的经验,一番努力下来也算是有所收获,虽说现在船已经不在身边,但还是想凭着记忆把制作过程捋一遍,就当是记录学习过程吧(该文章仅供参考,相信各位看我文章只图一乐,真做起来当然会比我初出茅庐做得好啦)
非保姆级非保姆级非保姆级,细节处需要思考,谢谢
设计思路:
可以看见所需理解并使用的功能有: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组.0
USART1_Init(9600);
NRF24L01_Init();
ADCx_Init();
TIM1_PWM_Init(9999,143);
TIM3_CH1_PWM_Init(199,7199);//20ms
printf("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;
else
val1=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); // 初始化指定IO
GPIO_ResetBits(GPIOB,GPIO_Pin_10|GPIO_Pin_12); // PB10、PB12输出低
//为低的话实际是使能片选,但是因为C8T6上面没有W25Q128,所以使能没问题
/*这个应该是CE、使能芯片的接发模式*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_I