1、摄像头模块
测试程序(main.c)
#include "cam.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
int main()
{
unsigned int width,height,size,ismjpeg,index;
unsigned char *jpeg_ptr = NULL;
width = 320;
height = 240;
int fd = camera_init("/dev/video0",&width, &height, &size, &ismjpeg);
if(fd < 0)
{
return -1;
}
camera_start(fd);
signal(SIGPIPE, SIG_IGN);
int i = 0;
for(i = 0; i < 10; i++)
{
camera_dqbuf(fd,(void **) &jpeg_ptr, &size, &index);
printf("jpeg_ptr:%p\tsize:%d\n",jpeg_ptr,size);
char fn[10] = {0};
sprintf(fn,"%d.jpg",i);
int myf = open(fn, O_WRONLY | O_CREAT, 0664);
write(myf, jpeg_ptr, size);
close(myf);
sleep(5);
camera_eqbuf(fd, index);
}
camera_stop(fd);
camera_exit(fd);
return 0;
}
依赖的摄像头驱动程序
cam.h 头文件
#ifndef __CAM_H__
#define __CAM_H__
#include <sys/types.h>
/*store picture buf*/
struct cam_buf
{
void *start;
size_t length;
};
int camera_init(char *devpath, unsigned int *width, unsigned int *height, unsigned int *size, unsigned int *ismjpeg);
int camera_start(int fd);
int camera_dqbuf(int fd, void **buf, unsigned int *size, unsigned int *index);
int camera_eqbuf(int fd, unsigned int index);
int camera_stop(int fd);
int camera_exit(int fd);
#endif
cam.c
#include <stdio.h>
#include "cam.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#define REQBUFS_COUNT 4
struct v4l2_requestbuffers reqbufs;
struct cam_buf bufs[REQBUFS_COUNT];
int camera_init(char *devpath, unsigned int *width, unsigned int *height, unsigned int *size, unsigned int *ismjpeg)
{
int i;
int fd = -1;
int ret;
struct v4l2_buffer vbuf;
struct v4l2_format format;
struct v4l2_capability capability;
/*open device of video*/
if((fd = open(devpath, O_RDWR)) == -1)
{
perror("open");
return -1;
}
/*ioctl look support drives*/
ret = ioctl(fd, VIDIOC_QUERYCAP, &capability);
if(ret == -1)
{
perror("camera->init");
return -1;
}
/*look support video capture yes or no*/
if(!(capability.capabilities & V4L2_CAP_VIDEO_CAPTURE))
{
fprintf(stderr, "camera->init: device can not supprot V4L2_CAP_VIDEO_CAPTURE.\n");
close(fd);
return -1;
}
/*look device support video stream yes or no*/
if(!(capability.capabilities & V4L2_CAP_STREAMING))
{
fprintf(stderr,"camera->init: device can not support V4L2_CAP_STREAMING.\n");
close(fd);
return -1;
}
/*set capture format MJPEG*/
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
format.fmt.pix.width = *width;
format.fmt.pix.height = *height;
format.fmt.pix.field = V4L2_FIELD_ANY;
ret = ioctl(fd, VIDIOC_S_FMT, &format);
if(ret == -1)
{
perror("camera init");
return -1;
}
else
{
*ismjpeg = 0;
fprintf(stdout, "camera->init: picture format is mjpeg\n");
goto get_fmt;
}
/*set capture format YUYV*/
memset(&format, 0, sizeof(format));
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //永远都是这个类型
format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; //设置采集图片的格式
format.fmt.pix.width = *width;
format.fmt.pix.height = *height;
format.fmt.pix.field = V4L2_FIELD_ANY; //设置图片一行一行的采集
ret = ioctl(fd, VIDIOC_S_FMT, &format); //ioctl 是设置生效
if(ret == -1)
{
perror("camera init");
}
else
{
fprintf(stdout, "camera->init: picture format is yuyv\n");
*ismjpeg = 1;
goto get_fmt;
}
get_fmt:
ret = ioctl(fd, VIDIOC_G_FMT, &format);
if (ret == -1)
{
perror("camera init");
return -1;
}
/*向驱动申请缓存*/
memset(&reqbufs, 0, sizeof(struct v4l2_requestbuffers));
reqbufs.count = REQBUFS_COUNT; //缓存区个数
reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbufs.memory = V4L2_MEMORY_MMAP; //设置操作申请缓存的方式:映射 MMAP
ret = ioctl(fd, VIDIOC_REQBUFS, &reqbufs);
if (ret == -1)
{
perror("camera init");
close(fd);
return -1;
}
/*循环映射并入队*/
for (i = 0; i < reqbufs.count; i++)
{
/*真正获取缓存的地址大小*/
memset(&vbuf, 0, sizeof(struct v4l2_buffer));
vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
vbuf.memory = V4L2_MEMORY_MMAP;
vbuf.index = i;
ret = ioctl(fd, VIDIOC_QUERYBUF, &vbuf);
if (ret == -1)
{
perror("camera init");
close(fd);
return -1;
}
/*映射缓存到用户空间,通过mmap讲内核的缓存地址映射到用户空间,并切和文件描述符fd相关联*/
bufs[i].length = vbuf.length;
bufs[i].start = mmap(NULL, vbuf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, vbuf.m.offset);
if (bufs[i].start == MAP_FAILED)
{
perror("camera init");
close(fd);
return -1;
}
/*每次映射都会入队,放入缓冲队列*/
vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
vbuf.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd, VIDIOC_QBUF, &vbuf);
if (ret == -1) {
perror("camera init");
close(fd);
return -1;
}
}
/*返回真正设置成功的宽.高.大小*/
*width = format.fmt.pix.width;
*height = format.fmt.pix.height;
*size = bufs[0].length;
return fd;
}
int camera_start(int fd)
{
int ret;
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
/*ioctl控制摄像头开始采集*/
ret = ioctl(fd, VIDIOC_STREAMON, &type);
if (ret == -1)
{
perror("camera->start");
return -1;
}
fprintf(stdout, "camera->start: start capture\n");
return 0;
}
int camera_dqbuf(int fd, void **buf, unsigned int *size, unsigned int *index)
{
int ret;
fd_set fds;
struct timeval timeout;
struct v4l2_buffer vbuf;
while (1)
{
FD_ZERO(&fds);
FD_SET(fd, &fds);
timeout.tv_sec = 4;
timeout.tv_usec = 0;
ret = select(fd + 1, &fds, NULL, NULL, &timeout); //使用select机制,保证fd有图片的时候才能出对
if (ret == -1)
{
perror("camera->dbytesusedqbuf");
if (errno == EINTR)
continue;
else
return -1;
}
else if (ret == 0)
{
fprintf(stderr, "camera->dqbuf: dequeue buffer timeout\n");
return -1;
}
else
{
vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
vbuf.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd, VIDIOC_DQBUF, &vbuf); //出队,也就是从用户空间取出图片
if (ret == -1)
{
perror("camera->dqbuf");
return -1;
}
*buf = bufs[vbuf.index].start;
*size = vbuf.bytesused;
*index = vbuf.index;
return 0;
}
}
}
int camera_eqbuf(int fd, unsigned int index)
{
int ret;
struct v4l2_buffer vbuf;
vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
vbuf.memory = V4L2_MEMORY_MMAP;
vbuf.index = index;
ret = ioctl(fd, VIDIOC_QBUF, &vbuf); //入队
if (ret == -1)
{
perror("camera->eqbuf");
return -1;
}
return 0;
}
int camera_stop(int fd)
{
int ret;
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
if (ret == -1)
{
perror("camera->stop");
return -1;
}
fprintf(stdout, "camera->stop: stop capture\n");
return 0;
}
int camera_exit(int fd)
{
int i;
int ret;
struct v4l2_buffer vbuf;
vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
vbuf.memory = V4L2_MEMORY_MMAP;
for (i = 0; i < reqbufs.count; i++)
{
ret = ioctl(fd, VIDIOC_DQBUF, &vbuf);
if (ret == -1)
break;
}
for (i = 0; i < reqbufs.count; i++)
munmap(bufs[i].start, bufs[i].length);
fprintf(stdout, "camera->exit: camera exit\n");
return close(fd);
}
2、串口模块
serial.h
#ifndef __SERIAL_H__
#define __SERIAL_H__
/*
*function_name: uart_set
*function: configure uart arguments
*arguments:
* int fd: open serial device return the file descriptor
* int speed: baud rate
* int flow_ctrl: flow control
* int databits: data bits
* int stopbits: stop bits
* int parity: parity
*return: 0 is success, -1 is error.
*/
int uart_set(int fd, int speed, int flow_ctrl, int databits, int stopbits, int parity);
/*
*function_name: init_uart
*function: init uart(open the serial device and configure uart arguments)
*arguments: void
*return: serial device file descriptor is success, -1 is error.
*/
int init_uart();
/*
*function_name: writecmd
*function: send str by serial port
*arguments:
* int fd: serial device file descriptor
* const char *str: control command
*return: sucess return write data len, -1 is error.
*/
int writecmd(int fd, const unsigned char *str);
/*
*function_name: recvmsg
*function: recv message form serial ports.
*arguments:
* int fd: serial device file descriptor
* char *buf: send buf
* int data_len: want to send buf len
*return: success is len(>0), -1 is error.
*/
int myrecvmsg(int fd, char *buf, int data_len);
#endif
serial.c
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include "serial.h"
#include <poll.h>
#include <sys/select.h>
//int uart_set(int fd, int speed, int flow_ctrl, int databits, int stopbits, int parity);
//int init_uart();
//int writecmd(const char *str);
int writecmd(int fd, const unsigned char *str)
{
if(fd < 0)
{
puts("fd < 0");
return -1;
}
if(NULL == str)
{
puts("str is null pointer.");
return -1;
}
/*
unsigned char buf[5] = {0xff, 0x00, 0x00, 0x00, 0xff};
if(strstr(str, "go_starght"))
{
buf[2] = 0x01;
}
else if(strstr(str, "go_back"))
{
buf[2] = 0x02;
}
else if(strstr(str, "go_left"))
{
buf[2] = 0x03;
}
else if(strstr(str, "go_right"))
{
buf[2] = 0x04;
}
else if(strstr(str, "stop"))
{
buf[2] = 0x00;
}
*/
static struct pollfd fds;
fds.fd = fd;
fds.events = POLLOUT;
fds.revents = 0;
/*60 second timeout*/
int ret = poll(&fds, 1, 600);
if(0 >= ret)
{
perror("[write_serial]poll");
return -1;
}
if(fds.revents & POLLOUT)
{
ret = write(fd, str, 2);
int i = 0;
for(i = 0; i < 2; i++)
{
printf("%x ",str[i]);
}
printf("\nret = %d\n",ret);
return ret;
}
else
{
return -1;
}
}
int init_uart()
{
//serial_init
//open ttyUSB0
int fd_ser = -1;
fd_ser = open("/dev/ttyATH0", O_RDWR | O_NOCTTY);
if(fd_ser < 0)
{
perror("open serial");
return -1;
}
//int ret_s = uart_set(fd_ser, 115200, 0, 8, 1, 'N');
int ret_s = uart_set(fd_ser, 9600, 0, 8, 1, 'N');
printf("ret_s:%d\n",ret_s);
printf("serial->init:init serial success.\n");
return fd_ser;
}
int uart_set(int fd, int speed, int flow_ctrl, int databits, int stopbits, int parity)
{
int i;
int status;
int speed_arr[] = {B115200, B19200, B9600, B4800, B2400, B1200, B300};
int name_arr[] = {115200, 19200, 9600, 4800, 2400, 1200, 300};
struct termios options;
if(tcgetattr(fd, &options) != 0)
{
perror("SetupSerial 1");
return 0;
}
//set baud
for(i = 0; i < sizeof(speed_arr) / sizeof(int); i++)
{
if(speed == name_arr[i])
{
cfsetispeed(&options, speed_arr[i]);
cfsetospeed(&options, speed_arr[i]);
}
}
options.c_cflag |= CLOCAL;
options.c_cflag |= CREAD;
switch(flow_ctrl)
{
case 0:
options.c_cflag &= ~CRTSCTS;
break;
case 1:
options.c_cflag &= CRTSCTS;
break;
case 2:
options.c_cflag |= IXON | IXOFF | IXANY;
break;
}
options.c_cflag &= ~CSIZE;
switch(databits)
{
case 5:
options.c_cflag |= CS5;
break;
case 6:
options.c_cflag |= CS6;
break;
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
puts("Unsupported data size");
return 0;
}
switch(parity)
{
case 'n':
case 'N':
options.c_cflag &= ~PARENB;
options.c_iflag &= ~INPCK;
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB);
options.c_iflag |= INPCK;
break;
case 'e':
case 'E':
options.c_cflag |= PARENB;
options.c_cflag |= ~PARODD;
options.c_iflag |= INPCK;
break;
case 's':
case 'S':
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default:
puts("Unsupport parity");
return 0;
}
switch (stopbits)
{
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
puts("Unsupported stop bits");
return 0;
}
options.c_oflag &= ~OPOST;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_cc[VTIME] = 1;
options.c_cc[VMIN] = 1;
tcflush(fd, TCIFLUSH);
if(tcsetattr(fd, TCSANOW, &options) != 0)
{
perror("com set error");
return 0;
}
return 1;
}
int myrecvmsg(int fd, char *buf, int data_len)
{
if(fd < 0)
{
puts("fd < 0");
return -1;
}
if(NULL == buf)
{
puts("buf is null.");
return -1;
}
//select serial port
int len, fs_sel;
fd_set fs_read;
struct timeval time;
FD_ZERO(&fs_read);
FD_SET(fd, &fs_read);
time.tv_sec = 10;
time.tv_usec = 0;
fs_sel = select(fd+1, &fs_read, NULL, NULL, &time);
if(fs_sel)
{
len = read(fd, buf, data_len);
return len;
}
else
{
return -1;
}
}
3、网络(socket)v1
主要功能:向串口发送消息
net1.h
#ifndef __NET1_H__
#define __NET1_H__
int init_net1();
int do_work1(int connfd1);
#endif
net1.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include "serial.h"
int init_net1()
{
int ser_fd1 = -1;
//socket
ser_fd1 = socket(AF_INET, SOCK_STREAM, 0);
if(ser_fd1 < 0)
{
puts("socket1 error.");
return ser_fd1;
}
puts("socket1 success.");
//bind
struct sockaddr_in myser;
memset(&myser, 0, sizeof(myser));
myser.sin_family = AF_INET;
myser.sin_port = htons(7777);
myser.sin_addr.s_addr = htonl(INADDR_ANY);
int ret = bind(ser_fd1, (struct sockaddr *)&myser, sizeof(myser));
if(ret != 0)
{
puts("bind1 error.");
close(ser_fd1);
ser_fd1 = -1;
return ser_fd1;
}
puts("bind1 success.");
//listen
ret = listen(ser_fd1, 5);
if(ret != 0)
{
puts("listen1 error.");
close(ser_fd1);
ser_fd1 = -1;
return ser_fd1;
}
puts("listen1 success.");
return ser_fd1;
}
// 向串口发送消息
int do_work1(int connfd1)
{
if(connfd1 < 0)
{
puts("connfd1 < 0");
return -1;
}
int fd_uart = init_uart();
char cmd[50];
memset(cmd, 0, sizeof(cmd));
int ret;
while(1)
{
memset(cmd, 0, sizeof(cmd));
ret = recv(connfd1, cmd, sizeof(cmd), 0);
if(ret > 0)
{
if(strcmp(cmd,"qq") == 0);
{
writecmd(fd_uart,"qq");
}
else if(strcmp(cmd,"hh") == 0);
{
writecmd(fd_uart,"hh");
}
else if(strcmp(cmd,"ll") == 0);
{
writecmd(fd_uart,"ll");
}
else if(strcmp(cmd,"rr") == 0);
{
writecmd(fd_uart,"rr");
}
else if(strcmp(cmd,"ss") == 0);
{
writecmd(fd_uart,"ss");
}
}
}
close(fd_uart);
return 0;
}
对do_work改进
int do_work1(int connfd1)
{
if(connfd1 < 0)
{
puts("connfd1 < 0");
return -1;
}
puts("do work1");
int fd_uart = init_uart();
char cmd[50];
char zxc[]={0xff,0x00,0x00,0x00,};
memset(cmd, 0, sizeof(cmd));
int ret;
while(1)
{
memset(cmd, 0, sizeof(cmd));
ret = recv(connfd1, cmd, sizeof(cmd), 0);
if(ret > 0)
{
if(strcmp(cmd,"q") == 0);
{
zxc[2] = 0x01;
writecmd(fd_uart,zxc);
}
if(strcmp(cmd,"h") == 0);
{
zxc[2] = 0x02;
writecmd(fd_uart,zxc);
}
if(strcmp(cmd,"l") == 0);
{
zxc[2] = 0x03;
writecmd(fd_uart,zxc);
}
if(strcmp(cmd,"r") == 0);
{
zxc[2] = 0x04;
writecmd(fd_uart,zxc);
}
if(strcmp(cmd,"s") == 0);
{
zxc[2] = 0x00;
writecmd(fd_uart,zxc);
}
}
}
return 0;
}
4、网络(socket)v2
相比于上一版本,这一版本多了几个函数用于通信
同时开两个,用到了net1、mynet
主要功能:发送连续的图片信息
测试 main.c
#include "mynet.h"
#include "serial.h"
#include "net1.h"
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
int ser_fd = init_net();
int ser_fd1 = init_net1();
if(ser_fd < 0)
{
puts("init_net error.");
return -1;
}
if(ser_fd1 < 0)
{
puts("init_net1 error.");
return -1;
}
int connfd = -1;
int connfd1 = -1;
struct sockaddr_in mycli;
int len = sizeof(mycli);
connfd = accept(ser_fd, (struct sockaddr *)&mycli, &len);
//struct sockaddr_in mycli;
//int len = sizeof(mycli);
connfd1 = accept(ser_fd1, (struct sockaddr *)&mycli, &len);
if(connfd < 0)
{
puts("accept error.");
close(ser_fd);
return -1;
}
puts("accept success.");
if(connfd1 < 0)
{
puts("accept1 error.");
close(ser_fd1);
return -1;
}
puts("accept1 success.");
do_work(connfd);
do_work1(connfd1);
close(ser_fd);
close(ser_fd1);
return 0;
}
mynet.h
#ifndef __MYNET_H__
#define __MYNET_H__
int init_net();
int do_work(int connfd);
int get_file_name(char *filename, char *cmd);
int get_req(char *myreq, char *cmd);
int get_file_len(int fd);
#endif
mynet.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include "cam.h"
#include <signal.h>
int init_net()
{
int ser_fd = -1;
//socket
ser_fd = socket(AF_INET, SOCK_STREAM, 0);
if(ser_fd < 0)
{
puts("socket error.");
return ser_fd;
}
puts("socket success.");
//bind
struct sockaddr_in myser;
memset(&myser, 0, sizeof(myser));
myser.sin_family = AF_INET;
myser.sin_port = htons(8888);
myser.sin_addr.s_addr = htonl(INADDR_ANY);
int ret = bind(ser_fd, (struct sockaddr *)&myser, sizeof(myser));
if(ret != 0)
{
puts("bind error.");
close(ser_fd);
ser_fd = -1;
return ser_fd;
}
puts("bind success.");
//listen
ret = listen(ser_fd, 5);
if(ret != 0)
{
puts("listen error.");
close(ser_fd);
ser_fd = -1;
return ser_fd;
}
puts("listen success.");
return ser_fd;
}
int get_file_name(char *filename, char *cmd)
{
if(NULL == filename && NULL == cmd)
{
puts("get_file_name:error.");
return -1;
}
char *p = cmd+4;
int len = strlen(cmd);
cmd[len-1] = 0;
strcpy(filename, p);
return 0;
}
int get_req(char *myreq, char *cmd)
{
if(NULL == myreq && NULL == cmd)
{
puts("get_req:error.");
return -1;
}
char *p = cmd;
int i = 0;
while(*p != ' ')
{
myreq[i] = *p;
i++;
p++;
}
myreq[i] = 0;
return 0;
}
int get_file_len(int fd)
{
if(fd < 0)
{
puts("get file len error.");
return -1;
}
int len = lseek(fd, 0, SEEK_SET);
len = lseek(fd, 0, SEEK_END);
return len;
}
int do_work(int connfd)
{
if(connfd < 0)
{
puts("connfd < 0");
return -1;
}
puts("do_work");
char cmd[50];
memset(cmd, 0, sizeof(cmd));
int ret = recv(connfd, cmd, sizeof(cmd), 0);
if(ret > 0)
{
unsigned int width,height,size,ismjpeg,index;
unsigned char *jpeg_ptr = NULL;
width = 320;
height = 240;
int fd = camera_init("/dev/video0",&width, &height, &size, &ismjpeg);
if(fd < 0)
{
return -1;
}
camera_start(fd);
signal(SIGPIPE, SIG_IGN);
//puts(cmd);
char filename[40] = {0};
get_file_name(filename,cmd);
puts(filename);
char req[5] = {0};
get_req(req,cmd);
puts(req);
if(strcmp(req,"get") == 0)
{
while(1)
{
camera_dqbuf(fd,(void **) &jpeg_ptr, &size, &index);
char filelen[20] = {0};
sprintf(filelen,"len:%d",size);
puts(filelen);
send(connfd, filelen, 20, 0);
send(connfd, jpeg_ptr, size, 0);
camera_eqbuf(fd, index);
}
camera_stop(fd);
camera_exit(fd);
}
else
{
camera_stop(fd);
camera_exit(fd);
}
}
return 0;
}
5、电机模块(32)
stm32f1
主程序 main.c
/**
******************************************************************************
* File Name : main.c
* Description : Main program body
******************************************************************************
*
* COPYRIGHT(c) 2021 STMicroelectronics
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
/* USER CODE BEGIN Includes */
#define MOTOR_A_EN_GPIO GPIOA
#define MOTOR_A_EN_PIN GPIO_PIN_0
#define MOTOR_A_CON1_GPIO GPIOA
#define MOTOR_A_CON1_PIN GPIO_PIN_2
#define MOTOR_A_CON2_GPIO GPIOB
#define MOTOR_A_CON2_PIN GPIO_PIN_9
#define MOTOR_B_CON1_GPIO GPIOA
#define MOTOR_B_CON1_PIN GPIO_PIN_1
#define MOTOR_B_CON2_GPIO GPIOC
#define MOTOR_B_CON2_PIN GPIO_PIN_9
#define MOTOR_B_EN_GPIO GPIOA
#define MOTOR_B_EN_PIN GPIO_PIN_3
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim2;
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
void Change_Pulse(uint16_t left,uint16_t right);
void go_left(void);
void go_right(void);
void Straight(void);
void StraightB(void);
void Stop(void);
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
uint8_t c[2] = {0};
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM2_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_4);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
HAL_UART_Receive_IT(&huart1, c, 2);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/** System Clock Configuration
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
}
/* TIM2 init function */
void MX_TIM2_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig;
TIM_OC_InitTypeDef sConfigOC;
htim2.Instance = TIM2;
htim2.Init.Prescaler = 800;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 999;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_PWM_Init(&htim2);
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 999;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4);
}
/* USART1 init function */
void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart1);
}
/** Configure pins as
* Analog
* Input
* Output
* EVENT_OUT
* EXTI
*/
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__GPIOA_CLK_ENABLE();
__GPIOC_CLK_ENABLE();
__GPIOB_CLK_ENABLE();
/*Configure GPIO pins : PA1 PA2 */
GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : PC9 */
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pins : PB6 PB7 PB8 PB9 */
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart ==&huart1)
{
if(c[0] == 'q')
{
Straight();
}
else if(c[0] == 'h')
{
StraightB();
}
else if(c[0] == 'l')
{
go_left();
}
else if(c[0] == 'r')
{
go_right();
}
else if(c[0] == 's')
{
Stop();
}
}
}
void Change_Pulse(uint16_t left,uint16_t right)
{
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, left);
__HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_4, right);
}
//-----------------------------------------------
void go_left(void)//向左矫正
{
Change_Pulse(0,200);
HAL_GPIO_WritePin(MOTOR_A_CON1_GPIO, MOTOR_A_CON1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_A_CON2_GPIO, MOTOR_A_CON2_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_B_CON1_GPIO, MOTOR_B_CON1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_B_CON2_GPIO, MOTOR_B_CON2_PIN, GPIO_PIN_SET);
}
//------------------------------------------------
void go_right(void)//向右矫正
{
Change_Pulse(200,0);
HAL_GPIO_WritePin(MOTOR_A_CON1_GPIO, MOTOR_A_CON1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_A_CON2_GPIO, MOTOR_A_CON2_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_B_CON1_GPIO, MOTOR_B_CON1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_B_CON2_GPIO, MOTOR_B_CON2_PIN, GPIO_PIN_SET);
}
//-----------------------------------------------------
void Straight(void) //直行
{
Change_Pulse(200,200);
HAL_GPIO_WritePin(MOTOR_A_CON1_GPIO, MOTOR_A_CON1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_A_CON2_GPIO, MOTOR_A_CON2_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_B_CON1_GPIO, MOTOR_B_CON1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_B_CON2_GPIO, MOTOR_B_CON2_PIN, GPIO_PIN_SET);
}
void StraightB(void) //直行往后
{
Change_Pulse(200,200);
HAL_GPIO_WritePin(MOTOR_A_CON1_GPIO, MOTOR_A_CON1_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_A_CON2_GPIO, MOTOR_A_CON2_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_B_CON1_GPIO, MOTOR_B_CON1_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR_B_CON2_GPIO, MOTOR_B_CON2_PIN, GPIO_PIN_RESET);
}
void Stop(void) //停止
{
Change_Pulse(0,0);
HAL_GPIO_WritePin(MOTOR_A_CON1_GPIO, MOTOR_A_CON1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_A_CON2_GPIO, MOTOR_A_CON2_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_B_CON1_GPIO, MOTOR_B_CON1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR_B_CON2_GPIO, MOTOR_B_CON2_PIN, GPIO_PIN_RESET);
}
/* USER CODE END 4 */
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
6、ui模块(接受图片信息和发送指令)
使用qt完成(c++)
last1.pro
#-------------------------------------------------
#
# Project created by QtCreator 2021-07-27T16:30:56
#
#-------------------------------------------------
QT += core gui network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = last1
TEMPLATE = app
SOURCES += main.cpp\
widget.cpp
HEADERS += widget.h
FORMS += widget.ui
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QTcpSocket>
#include <QDebug>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
ui->lineEdit_ipaddr->setText("192.168.1.1");
ui->lineEdit_port->setText("8888");
ui->lineEdit_port1->setText("7777");
this->mysck = new QTcpSocket();
this->myser1 = new QTcpSocket();
this->flags = 0;
this->myser1->connectToHost(ui->lineEdit_ipaddr->text(),7777);
this->setWindowTitle("视频客户端");
connect(this->mysck, SIGNAL(connected()), this, SLOT(myconnect_success()));
connect(this->mysck, SIGNAL(readyRead()), this, SLOT(recv_pic_show()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_connect_clicked()
{
this->mysck->connectToHost(ui->lineEdit_ipaddr->text(), ui->lineEdit_port->text().toShort());
}
void Widget::myconnect_success()
{
ui->label_pic->setText("连接服务器成功");
}
void Widget::on_pushButton_recv_pic_clicked()
{
ui->label_pic->clear();
QString cmd = "get 1.jpg\n";
this->mysck->write(cmd.toLatin1());
}
void Widget::recv_pic_show()
{
if(this->flags == 0)
{
char flen[20] = {0};
this->mysck->read(flen,20);
qDebug() << flen;
this->flags = 1;
fl = atoi(flen+4);
}
else if(this->flags == 1)
{
qDebug() << fl;
char *mypb = NULL;
mypb = (char *)malloc(fl);
memset(mypb,0,fl);
if(this->mysck->bytesAvailable() >= fl)
{
this->mysck->read(mypb, fl);
this->pic = new QPixmap();
this->pic->loadFromData((unsigned char *)mypb,fl,"jpeg");
ui->label_pic->setPixmap(*pic);
this->flags = 0;
}
}
}
void Widget::on_pushButton_w_clicked()
{
this->myser1->write("qq");
}
void Widget::on_pushButton_b_clicked()
{
this->myser1->write("hh");
}
void Widget::on_pushButton_l_clicked()
{
this->myser1->write("ll");
}
void Widget::on_pushButton_r_clicked()
{
this->myser1->write("rr");
}
void Widget::on_pushButton_s_clicked()
{
this->myser1->write("ss");
}
void Widget::on_pushButton_test_pressed()
{
this->myser1->write("qq");
}
void Widget::on_pushButton_test_released()
{
this->myser1->write("ss");
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPixmap>
#include <QTcpSocket>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
public:
QTcpSocket *mysck,*myser1;
QPixmap *pic;
int flags;
int fl;
private slots:
void on_pushButton_connect_clicked();
void myconnect_success();
void on_pushButton_recv_pic_clicked();
void recv_pic_show();
void on_pushButton_w_clicked();
void on_pushButton_b_clicked();
void on_pushButton_l_clicked();
void on_pushButton_r_clicked();
void on_pushButton_s_clicked();
void on_pushButton_test_pressed();
void on_pushButton_test_released();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
widget.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>368</width>
<height>534</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<widget class="QLabel" name="label_pic">
<property name="geometry">
<rect>
<x>20</x>
<y>70</y>
<width>320</width>
<height>240</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>320</width>
<height>240</height>
</size>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_w">
<property name="geometry">
<rect>
<x>140</x>
<y>370</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>前</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_l">
<property name="geometry">
<rect>
<x>12</x>
<y>417</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>左</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_r">
<property name="geometry">
<rect>
<x>250</x>
<y>420</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>右</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_b">
<property name="geometry">
<rect>
<x>140</x>
<y>470</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>后</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_s">
<property name="geometry">
<rect>
<x>140</x>
<y>420</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>停</string>
</property>
</widget>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>20</x>
<y>10</y>
<width>331</width>
<height>23</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_1">
<property name="text">
<string>IP地址:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_ipaddr"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>20</x>
<y>40</y>
<width>331</width>
<height>23</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>端口号:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_port"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>330</y>
<width>351</width>
<height>30</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="pushButton_connect">
<property name="text">
<string>连接成功</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_recv_pic">
<property name="text">
<string>接受视频</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QLineEdit" name="lineEdit_port1">
<property name="geometry">
<rect>
<x>10</x>
<y>370</y>
<width>113</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="pushButton_test">
<property name="geometry">
<rect>
<x>250</x>
<y>370</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>测试</string>
</property>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>