赞
踩
本项目本质为客户端与服务器之间的通信,通过发送不同的指令,服务器和客户端进行不同的操作。
客户端:基于STM32制作简单行驶小车
服务器:安卓手机,基于Socket编程下 用QT进行安卓开发,将app传输到手机上。
TCP通信:ESP8266
手机端发送不同指令,小车执行不同操作
1. esp8266WiFi模块
2. 直流电机
(笔者这里用编码器电机代替,普通直流电机即可)
3. STM32F103C8T8
4. 驱动电机模块
(笔者这里用的是TB6612,L298N啥的都行)
5. 烧写器 ST-Link
6. 安卓手机
7. 电池、杜邦线、螺母、轮胎等等
1. pwm
void TIM3_PWM_Init(u16 per,u16 psc) { /*使能TIM4时钟*/ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); /*使能GPIO*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); /*使能AFIO*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); /*配置GPIO*/ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStructure); /*设置重映射*/ //GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);//部分重映射 /*初始化定时器参数*/ TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频为1分频 TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//选择计数模式为向上计数 TIM_TimeBaseInitStructure.TIM_Period = per;//配置周期(ARR自动重装器的值) TIM_TimeBaseInitStructure.TIM_Prescaler = psc;//配置PSC预分频器的值 //TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值,高级计数器才需配置 TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure); //TIM_ClearFlag(TIM4,TIM_FLAG_Update);//先清除标志位,避免刚初始化就进入中断 /*初始化PWM参数*/ TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; //选择空闲状态下的非工作状态 低电平 TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set; //选择互补空闲状态下的非工作状态 低电平 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//选择PWM1模式 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出极性:高电平有效 TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //输出比较使能 TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //互补输出比较使能 TIM_OC1Init(TIM3,&TIM_OCInitStructure); TIM_OC2Init(TIM3,&TIM_OCInitStructure); TIM_OC3Init(TIM3,&TIM_OCInitStructure); TIM_OC4Init(TIM3,&TIM_OCInitStructure); /*使能TIMX在CCRX上的预装载寄存器*/ TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable); TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable); TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable); TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable); TIM_CtrlPWMOutputs(TIM3,ENABLE); /*使能TIMX在ARR上的预装载寄存器允许位*/ //TIM_ARRPreloadConfig(TIM4,ENABLE); /*开启定时器*/ TIM_Cmd(TIM3,ENABLE); }
2. Car
void forward() { GPIO_SetBits(GPIOB,GPIO_Pin_7| GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_15); GPIO_ResetBits(GPIOB,GPIO_Pin_8| GPIO_Pin_10 | GPIO_Pin_12 | GPIO_Pin_14); } void back() { GPIO_SetBits(GPIOB,GPIO_Pin_8| GPIO_Pin_10 | GPIO_Pin_12 | GPIO_Pin_14); GPIO_ResetBits(GPIOB,GPIO_Pin_7| GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_15); } // PB7,PB8: 右后 // PB14,PB15:右前 // PB12,PB13:左前 // PB10,PB11:左后 void turn_left() { GPIO_SetBits(GPIOB,GPIO_Pin_7| GPIO_Pin_10 | GPIO_Pin_13 | GPIO_Pin_15); GPIO_ResetBits(GPIOB,GPIO_Pin_8| GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_14); } void turn_left1() { GPIO_SetBits(GPIOB,GPIO_Pin_8| GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14); GPIO_ResetBits(GPIOB,GPIO_Pin_7| GPIO_Pin_10 | GPIO_Pin_12 | GPIO_Pin_15); } void turn_right() { GPIO_SetBits(GPIOB,GPIO_Pin_8| GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_15); GPIO_ResetBits(GPIOB,GPIO_Pin_7| GPIO_Pin_10 | GPIO_Pin_12 | GPIO_Pin_14); } void turn_right1() { GPIO_SetBits(GPIOB,GPIO_Pin_8| GPIO_Pin_10 | GPIO_Pin_12 | GPIO_Pin_15); GPIO_ResetBits(GPIOB,GPIO_Pin_7| GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14); } void stop(void) { GPIO_ResetBits(GPIOB,GPIO_Pin_8 | GPIO_Pin_7 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15); }
3. esp8266
void esp8266_start_trans(void) { //printf("等待初始化\r\n"); while(esp8266_send_cmd((u8 *)"AT",(u8 *)"OK",20)); //设置工作模式 1:station模式 2:AP模式 3:兼容 AP+station模式 while(esp8266_send_cmd((u8*)"AT+CWMODE=1",(u8*)"OK",20)); //printf("设置工作模式成功\r\n"); delay_ms(1000); //让模块连接上自己的路由 while(esp8266_send_cmd((u8*)"AT+CWJAP=\"226\",\"226226226\"",(u8*)"WIFI GOT IP",200)); //printf("连接路由器成功\r\n"); delay_ms(1000); //=0:单路连接模式 =1:多路连接模式 while(esp8266_send_cmd((u8*)"AT+CIPMUX=0",(u8*)"OK",200)){printf("设置单路连接模式失败\r\n");} //printf("设置单路连接模式成功\r\n"); delay_ms(1000); while(esp8266_send_cmd((u8*)"AT+CIPSTART=\"TCP\",\"192.168.124.66\",8080",(u8*)"OK",500)); //printf("TCP连接成功\r\n"); delay_ms(1000); //是否开启透传模式 0:表示关闭 1:表示开启透传 esp8266_send_cmd((u8*)"AT+CIPMODE=1",(u8*)"OK",200); //printf("开启透传模式\r\n"); esp8266_send_cmd((u8*)"AT+CIPSEND",(u8*)"OK",50); //printf("开启透传成功\r\n"); }
4. usart
void USART2_init(u32 bound) { NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // GPIOB时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); //串口3时钟使能 USART_DeInit(USART2); //复位串口3 //USART2_TX PB10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PB10 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PB10 //USART2_RX PB11 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PB11 USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART2, &USART_InitStructure); //初始化串口 3 USART_Cmd(USART2, ENABLE); //使能串口 //使能接收中断 USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断 //设置中断优先级 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 TIM2_Int_Init(1000-1,7200-1); //10ms中断 USART2_RX_STA=0; //清零 TIM_Cmd(TIM2,DISABLE); //关闭定时器7 }
5. time2
void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)//是更新中断 { USART2_RX_STA|=1<<15; //标记接收完成 TIM_ClearITPendingBit(TIM2, TIM_IT_Update ); //清除TIM2更新中断标志 TIM_Cmd(TIM2, DISABLE); //关闭TIM2 } } //通用定时器7中断初始化,这里时钟选择为APB1的2倍 //arr:自动重装值 psc:时钟预分频数 //定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us. //Ft=定时器工作频率,单位:Mhz //通用定时器中断初始化 void TIM2_Int_Init(u16 arr,u16 psc) { NVIC_InitTypeDef NVIC_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//TIM2时钟使能 //定时器TIM2初始化 TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位 TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE ); //使能指定的TIM2中断,允许更新中断 TIM_Cmd(TIM2,ENABLE);//开启定时器7 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子优先级2 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 }
6. main
int main(void) { unsigned char* m=NULL; int k1,k2,k3,k4,flag,f1,f2,f3; delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 uart_init(115200); //串口初始化为115200 USART2_init(115200); //串口初始化为115200 esp8266_quit_trans(); esp8266_start_trans(); //esp8266进行初始化 GPIOB_Init(); TIM3_PWM_Init(100-1,72-1); int i,j=15; flag=1; while(1) { m=WIFI_Rece_Data(); if(flag == 1) { m[0]='S'; flag = 0; } else if(m[0]=='F') i=0; else if(m[0]=='L') i=1; else if(m[0]=='R') i=3; else if(m[0]=='S') i=5; else if(m[0]=='B') i=7; else if(m[0]=='u'&& m[1]=='p') i=2; else if(m[0]=='u'&& m[1]=='d') i=4; switch(i) { case 0: f1=1; setpwm(j); forward(); break; case 1: f2=1; k1=j-15; k2=j+15; if(k1<=0) k1=0; if(k2>=100) k2=100; setpwm1(k1,k2); if(f1==1) turn_left(); if(f1==-1) turn_left1(); break; case 3: f3=1; k3=j+15; k4=j-15; if(k3>=100) k3=100; if(k4<=0) k4=0; setpwm1(k3,k4); if(f1==1) turn_right(); if(f1==-1) turn_right1(); break; case 5: stop(); break; case 7: f1=-1; setpwm(j); back(); break; case 2: if(f2==1) { k1+=2;k2+=10; if(k1>=30) k1=30; if(k2>=100) k2=100; setpwm1(k1,k2); delay_ms(20); f2=0; break; } else if(f3==1) { k3+=10;k4+=2; if(k3>=100) k3=100; if(k4>=30) k4=30; setpwm1(k3,k4); delay_ms(20); f3=0; break; } else { if(j>=100) j=100; setpwm(j); j++; delay_ms(50); break; } case 4: if(f2==1) { k1-=2;k2-=5; if(k1<=0) k1=0; if(k2<=30) k2=30; setpwm1(k1,k2); delay_ms(20);f2=0; break;} else if(f3==1) { k3-=5;k4-=2; if(k3<=30) k3=30; if(k4<=0) k4=0; setpwm1(k3,k4); delay_ms(20); f3=0;break;} else{ if(j<=0) j=0; setpwm(j); j--; delay_ms(50); break; } } } }
Server
server::server(QWidget *parent) : QWidget(parent), ui(new Ui::server) { ui->setupUi(this); tcpserver=nullptr; tcpsocket=nullptr; //创建监听套接字 tcpserver=new QTcpServer(this);//指定父对象 回收空间 //bind+listen tcpserver->listen(QHostAddress::Any,8080);//绑定当前网卡所有的ip 绑定端口 也就是设置服务器地址和端口号 //服务器建立连接 connect(tcpserver,&QTcpServer::newConnection,[=](){ //取出连接好的套接字 tcpsocket=tcpserver->nextPendingConnection(); //获得通信套接字的控制信息 QString ip=tcpsocket->peerAddress().toString();//获取连接的 ip地址 quint16 port=tcpsocket->peerPort();//获取连接的 端口号 QString temp=QString("[%1:%2] 客服端连接成功").arg(ip).arg(port); //显示连接成功 ui->textEditRead->setText(temp); }); } void server::on_forward_clicked() { if(tcpsocket==nullptr) return ; QString str="F"; tcpsocket->write(str.toUtf8().data()); } void server::on_back_clicked() { if(tcpsocket==nullptr) return ; QString str="B"; tcpsocket->write(str.toUtf8().data()); } void server::on_turn_left_clicked() { if(tcpsocket==nullptr) return ; QString str="L"; tcpsocket->write(str.toUtf8().data()); } void server::on_turn_right_clicked() { if(tcpsocket==nullptr) return ; QString str="R"; tcpsocket->write(str.toUtf8().data()); } void server::on_stop_clicked() { if(tcpsocket==nullptr) return ; QString str="S"; tcpsocket->write(str.toUtf8().data()); } void server::on_speed_up_clicked() { if(tcpsocket==nullptr) return ; QString str="up"; tcpsocket->write(str.toUtf8().data()); } void server::on_speed_down_clicked() { if(tcpsocket==nullptr) return ; QString str="ud"; tcpsocket->write(str.toUtf8().data()); }
基于STM32-Socket-Qt 遥控小车(一代)
若需程序源码 可评论区留言QQ邮箱 或 直接私信即可
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。