2023年电赛cw32分享

2024-03-22 13:59
文章标签 2023 分享 电赛 cw32

本文主要是介绍2023年电赛cw32分享,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2023年电赛E题开源分享

基于CW32的运动控制系统与自动追踪系统设计

(2023年全国大学生电子设计竞赛 E题)

  1. 全国大学生电子设计竞赛概述

    1.   全国大学生电子题计竞赛简介

    全国大学生电子设计竞赛(National Undergraduate Electronics Design Contest,简称TI杯)是教育部和工信部共同发起的大学生学科竞赛之一,该竞赛面向大学生群众性科技活动,目的在于推动高等学校促进信息与电子类学科课程体系和课程内容改革。竞赛的特点是与高等学校相关专业的课程体系和课程内容改革密切结合,以推动课程教学、教学改革和实验室建设工作。

    全国大学生电子设计竞赛从1997年开始每二年举办一届,竞赛时间定于竞赛举办年度的9月份,赛期四天。全国大学生电子设计竞赛每逢单数年的9月份举办,赛期四天三夜(具体日期届时通知)。在双数的非竞赛年份,根据实际需要由全国竞赛组委会和有关赛区组织开展全国的专题性竞赛,同时积极鼓励各赛区和学校根据自身条件适时组织开展赛区和学校一级的大学生电子设计竞赛。

    竞赛采用全国统一命题、分赛区组织的方式,竞赛采用“半封闭、相对集中”的组织方式进行。竞赛期间学生可以查阅有关纸介或网络技术资料,队内学生可以集体商讨设计思想,确定设计方案,分工负责、团结协作,以队为基本单位独立完成竞赛任务;竞赛期间不允许任何教师或其他人员进行任何形式的指导或引导;竞赛期间参赛队员不得与队外任何人员讨论商量。参赛学校应将参赛学生相对集中在实验室内进行竞赛,便于组织人员巡查。为保证竞赛工作,竞赛所需设备、元器件等均由各参赛学校负责提供。

一般赛题主要有以下几大类型:

  1. 电源类:简易数控直流电源、直流稳压电源;

  2. 信号源类:实用信号源的设计和制作、波形发生器、电压控制LC振荡器等;

  3. 高频无线电类:简易无线电遥控系统、调幅广播收音机、短波调频接收机、调频收音机等;

  4. 放大器类:实用低频功率放大器、高效率音频功率放大器、宽带放大器等;

  5. 仪器仪表类:简易电阻、电容和电感测试仪、简易数字频率计、频率特性测试仪、数字式工频有效值多用表、简易数字存储示波器、低频数字式相位测量仪、简易逻辑分析仪;

  6. 数据采集与处理类:多路数据采集系统、数字化语音存储与回放系统、数据采集与传输系统;

  7. 控制类:水温控制系统、自动往返电动小汽车、简易智能电动车、液体点滴速度监控装置。

  1. 2023年全国大学生电子设计竞赛E题题目及要求

    1.   任务

          设计制作一个运动目标控制与自动追踪系统。系统包括模拟目标运动的红色光斑位置控制系统和指示自动追踪的绿色光斑位置控制系统。系统结构示意及摆放位置见图1(a) 。图中两个激光笔固定在各自独立的二维电控云台上。

d8a3ebdf0afc48b9b0a30194da2ed328.png

 

  1. 红色激光笔发射的光斑用来模拟运动目标,光斑落在正前方距离 1m 处的白色屏幕上,光斑直径≤1cm。红色光斑位置控制系统控制光斑能在屏幕范围内任意移动。

  2. 绿色激光笔发射的光斑由绿色光斑位置系统控制,用于自动追踪屏幕上的红色光斑,指示目标的自动追踪效果,光斑直径≤1cm。绿色激光笔放置线段如图1(b)所示,该线段与屏幕平行,位于红色激光笔两侧,距红色激光笔距离大于0.4m、小于1m。绿色激光笔在两个放置线段上任意放置。

  3. 屏幕为白色,有效面积大于 0.6×0.6m(2)。用铅笔在屏幕中心画出一个边长0.5m 的正方形,标识屏幕的边线;所画的正方形的中心为原点,用铅笔画出原点位置,所用铅笔痕迹宽≤1mm。

  1. 要求

  1. 基本要求

设置运动目标位置复位功能。执行此功能,红色光斑能从屏幕任意位置回到原点。光斑中心距原点误差≤2cm。

启动运动目标控制系统。红色光斑能在30秒内沿屏幕四周边线顺时针移动一周,移动时光斑中心距边线距离≤2cm。

用约1.8cm宽的黑色电工胶带沿 A4 纸四边贴一个长方形,构成 A4 靶纸。将此A4靶纸贴在屏幕自定的位置。启动运动目标控制系统,红色光斑能30秒内沿胶带顺时针移动一周。超时不得分,光斑完全脱离胶带一次扣2分,连续脱离胶带移动 5cm 以上记为0分。

将上述 A4 靶纸以任意旋转角度贴在屏幕任意位置。启动运动目标控制系统,要求同iii。

  1. 发挥部分

运动目标位置复位,一键启动自动追踪系统,控制绿色光斑能在 2 秒内追踪红色光斑,追踪成功发出连续声光提示。此时两个光斑中心距离应≤3cm。

运动目标重复基本要求iii~iv的动作。绿色激光笔发射端可以放置在其放置线段的任意位置,同时启动运动目标及自动追踪系统,绿色光斑能自动追踪红色光斑。启动系统 2 秒后,应追踪成功,发出连续声光提示。此后,追踪过程中两个光斑中心距离大于 3cm 时,定义为追踪失败,一次扣 2 分。连续追踪失败3 秒以上记为 0 分。

运动目标控制系统和自动追踪系统均需设置暂停键。同时按下暂停键,红色和绿色光斑应立即制动,以便测量两个光斑中心距离。

  1. 其他。

      1.   说明

  1. 红色、绿色光斑位置控制系统必须相互独立,之间不得有任何方式通信;光斑直径小于 1cm;屏幕上无任何电子元件;控制系统不能采用台式计算机或笔记本电脑。不符合要求不进行测试。

  1. 基本要求iii、iv未得分不进行发挥部分ii 的测试。

详细题目内容参见网址:https://res.nuedc-training.com.cn/topic/2023/topic_99.html

  1. 系统总体设计方案

本小组已基本完成前三问,该运动目标控制系统能够较为精准、快速地实现运动目标(红色光斑)的复位、轨迹移动以及循迹功能。

2.1任务概述

根据题目要求,本项目拟设计制作一个运动目标控制与自动追踪系统,该系统包括模拟目标运动的红色光斑位置控制系统和指示自动追踪的绿色光斑位置控制系统。系统结构示意及摆放位置如图1(a)。两个激光笔固定在各自独立的电控云台上。

d194a2dcacbc41a4b958436ca85b2d6e.png

 

  1. 芯片选型

CW32F030X6/X8 是由武汉芯源半导体推出的一款国产32位微控制器,基于 eFlash ,集成了主频高达 64MHz 的 ARM® Cortex®-M0+ 内核、高速嵌入式存储器(多至 64K 字节 FLASH 和多至 8K 字节 SRAM)以及一系列全面的增强型外设和 I/O 口。所有型号都提供全套的通信接口(三路 UART、两路 SPI 和两路 I2C)、12 位高速 ADC、七组通用和基本定时器以及一组高级控制 PWM 定时器。CW32F030x6/x8 可以在 -40° C 到 105° C 的温度范围内工作,供电电压宽达 1.65V ~ 5.5V。支持 Sleep 和DeepSleep 两种低功耗工作模式。

综上所述,CW32F030CT86能够满足该任务设计需求,且成本较低,适合本项目设计的简单嵌入式系统。根据设计需求及资源,本项目中选择CW32芯片作为主控CPU。

  1. 运动控制理论及自动追踪方法

    1.    运动目标控制理论

在运动控制系统中,基于OpenMV识别目标点及轨迹并传送坐标数据给MCU,由主控MCU调整PWM输出占空比实现对舵机运动参数的调整,从而控制云台转动实现对运动目标的复位、轨迹移动、循迹等功能。

  1. 系统硬件设计

    1.    运动控制系统设计

本组完成的题目是根据红色斑点为基础,使用cw32作为主控,MG995舵机搭建二维云台,通过按键控制功能。

396edcf9e3084696a4744873675db781.png

 

  1. MCU

本项目采用国产32位微控制器CW32作为为主控MCU,如下图所示:

内核

ARM® Cortex®-M0+

Flash

64K,数据保持 25 年

SRAM

8K,支持奇偶校验

GPIO

39个GPIO,分别为PAO-PA15、PBO-PB15、PC13-PC15、PF0、PF1、PF6、PF7

Timers

16 位高级控制定时器,支持 6 路捕获 / 比较通道和 3 对互补 PWM 输出,死区时间和灵活的同步功能

四组 16 位通用定时器

看门狗定时器(独立看门狗IWDG、窗口看门狗WWDG)

工作电压

2V~3.6V

工作温度

-40°C ~105C

通信串口

2*IIC,2*SPI,3*USART

系统时钟

4 ~ 32MHz 晶体振荡器、32kHz 低速晶体振荡器、内置 48MHz RC 振荡器、内置 32kHz RC 振荡器、内置 10kHz RC 振荡器、内置 150kHz RC 振荡器、时钟监测系统、允许独立关断各外设时钟

  1. 云台

根据设计要求,比赛中舵机云台需要搭载激光笔,通过对舵机装置角度参数的控制完成对运动目标的控制。

舵机云台方面我们采用的时MG995舵机,由于比赛要求存在二维平面的运动控制,所以,我们采用两个舵机来进行组装成云台。舵机参数如下图所示:

产品名称

MG995舵机

产品重量

55g

转动速度

53-62r/m

工作扭矩

13kg/cm

使用温度

-30℃~+55℃

死区设定

4微秒

转动角度

180度/360度

使用电压

3-7.2V

工作电流

100mA

  1. OpenMV模块

      我们在电赛的过程中摄像头模块使用的时openmv模块,openmv模块在互联网上具有许多例程以及资料,并且能满足比赛期间的功能实现。具体参数如下

    处理器

    ARM 32bit Cortex-M7 CPUw/ Double Precision FPU 480 MHz (1027 DMIPS)

    RAM布局

    256KB . DATA/. BSS/Heap/Stack32MB Frame Buffer /Stack

    256 KB DMA Buffers

    FIash布局

    128KB Boot I oader

    16MB Embedded F lash Dr ive1792KB Fi rmware

    图像格式

    Grayscale、RGB565、JPEG (and BAYER)

    工作电压

    3.3V

    工作温度

    -20°C ~70C

    1.   openmv实现代码

    e9108828a43745afaff17311842e3dae.png

     

  1. 系统软件设计

    1.   运动控制系统程序设计

527bcd7e15ea4449b0747f09c5c97f73.png

 

  1. CW32

    cw32主控主函数。

33c433d1f1244e24ac0c753f8a19ec33.png

 

  1. 系统测试

  1. 测试方案设计

      根据题目要求进行测试,在规定时间和规定误差范围内进行测试,知道连续五次测试误差均在范围之内。

  1. 测试结果及分析

运动控制系统测试,在该环节测试中,前几次的测试存在很大的误差,由于电压问题导致云台出现种种原因,最终排除完外界因素后,运动系统有效的实现了对红色光斑的复位控制,并能够在30s内完成固定轨迹移动及循迹动作,并控制光斑距离小于2cm。

  1. 软件编写说明

  1. 运动控制系统

  1. 文件构成

  1. main.c---主函数

  2. duoji.c---舵机驱动

  3. openmv.c---串口发送数据

  4. mode.c---模式

  5. key.c---按键

  6. oled_iic.c---oled初始化,iic初始化

fc99ffb4ad2e4a688df260386c9930e5.png

 

  1. OLED

 

#include "oled_iic.h" #include "OLED_Font.h" uint8_t OLED_GRAM[144][8]; //IIC 引脚配置 void I2C_UserConfig(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; //开启GPIOB时钟 __RCC_GPIOB_CLK_ENABLE(); //RCC_AHBPeriphClk_Enable(RCC_AHB_PERIPH_GPIOB,ENABLE); //结构体初始化 GPIO_InitStructure.IT = GPIO_IT_NONE; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pins = IIC_SDA_GPIO_PIN; GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; GPIO_Init(IIC_SDA_GPIO_PORT,&GPIO_InitStructure); GPIO_InitStructure.IT = GPIO_IT_NONE; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Pins = IIC_SCL_GPIO_PIN; GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; GPIO_Init(IIC_SCL_GPIO_PORT,&GPIO_InitStructure); } //IIC SDA引脚模式切换函数 void I2C_SDA_Mode(uint8_t addr) { GPIO_InitTypeDef GPIO_InitStructure = {0}; if(addr)//如果是1 表示输出模式 { GPIO_InitStructure.IT = GPIO_IT_NONE; GPIO_InitStructure.Pins = IIC_SDA_GPIO_PIN; GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; } else//如果是0 表示输入模式 { GPIO_InitStructure.IT = GPIO_IT_NONE; GPIO_InitStructure.Pins = IIC_SDA_GPIO_PIN; GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP; } GPIO_Init(IIC_SDA_GPIO_PORT,&GPIO_InitStructure); } //IIC起始信号函数 void I2C_Start(void) { //第一步配置SDA引脚模式为输出 I2C_SDA_Mode(OUT); //启动时序开始 IIC_SCL_HIGH; IIC_SDA_HIGH; // delay_us(4); IIC_SDA_LOW; // delay_us(4); IIC_SCL_LOW; } //IIC停止信号函数 void I2C_Stop(void) { //第一步配置SDA引脚模式为输出 I2C_SDA_Mode(OUT); //停止时序 // IIC_SDA_LOW; // IIC_SCL_HIGH; // Delay_us(4); // IIC_SDA_HIGH; IIC_SDA_LOW; // delay_us(4); IIC_SCL_HIGH; // delay_us(4); IIC_SDA_HIGH; } //IIC读取相应函数 返回0表示成功;返回1表示失败 uint8_t I2C_Read_Ack(void) { uint8_t TimeAck; //第一步配置SDA引脚模式为输入 I2C_SDA_Mode(INPUT); //拉高SCL 因为在SCL为高电平时表示数据有效 IIC_SCL_HIGH; // delay_us(4); while(GPIO_ReadPin(IIC_SDA_GPIO_PORT,IIC_SDA_GPIO_PIN)) { //如果是1 表示失败 我们延时判断会 如果还超时了 那就是失败 if(++TimeAck > 250) { I2C_Stop(); return 1; } } IIC_SCL_LOW; // delay_us(3); return 0; } //IIC 字节写入函数 void I2C_Write_Byte(uint8_t Data) { uint8_t i = 0; //SCL为低电平时 数据进行切换 此时SDA无效 IIC_SCL_LOW; // delay_us(3); for(i=0;i<8;i++) { I2C_SDA_Mode(OUT); if( (Data<<i)&0x80 ) { IIC_SDA_HIGH; } else { IIC_SDA_LOW; } IIC_SCL_HIGH;//数据有效 // delay_us(3); IIC_SCL_LOW;//数据无效 数据切换 // delay_us(3); } } //读取数据函数 uint8_t I2C_Read_Data(void) { uint8_t i = 0; uint8_t Data ; for(i=0;i<8;i++) { I2C_SDA_Mode(INPUT); IIC_SCL_HIGH;//数据有效 // delay_us(3); Data<<=1; if(GPIO_ReadPin(IIC_SDA_GPIO_PORT,IIC_SDA_GPIO_PIN) == 1) { Data |= 0x01; } IIC_SCL_LOW;//数据无效 数据切换 // delay_us(3); } return Data; } /********************* OLED 0.96寸屏幕 相关函数 *******************************/ //OLED写指令函数 void OLED_Write_CMD(uint8_t cmd) { //第一步 发起起始信号 I2C_Start(); //第二步 发送从机设备地址 I2C_Write_Byte(OLED); I2C_Read_Ack();//等待从机响应 //第三步 发送的是数据还是命令,命令为0,数据为1 I2C_Write_Byte(0x00);//表示命令 I2C_Read_Ack();//等待从机响应 //第四步 发送目标数据 I2C_Write_Byte(cmd); I2C_Read_Ack();//等待从机响应 //第五步 发送停止信号 I2C_Stop(); // //delay_us(5);//适当延时 稳定数据 } //OLED写数据函数 void OLED_Write_Data(uint8_t data) { //第一步 发起起始信号 I2C_Start(); //第二步 发送从机设备地址 I2C_Write_Byte(OLED); I2C_Read_Ack();//等待从机响应 //第三步 发送的是数据还是命令,命令为0,数据为1 I2C_Write_Byte(0x40);//表示数据 I2C_Read_Ack();//等待从机响应 //第四步 发送目标数据 I2C_Write_Byte(data); I2C_Read_Ack();//等待从机响应 //第五步 发送停止信号 I2C_Stop(); //delay_us(5);//适当延时 稳定数据 } void OLED_SetCursor(uint8_t Y, uint8_t X) { OLED_Write_CMD(0xB0 | Y); //设置Y位置 OLED_Write_CMD(0x10 | ((X & 0xF0) >> 4)); //设置X位置低4位 OLED_Write_CMD(0x00 | (X & 0x0F)); //设置X位置高4位 } void OLED_Write_Clear(void) { uint8_t i = 0,j = 0; for(i=0;i<8;i++)//因为OLED 0.96寸屏 有8页 128列(128*64) { OLED_Write_CMD(0XB0|i);//遍历有多少行 OLED_Write_CMD(0X00); OLED_Write_CMD(0X10); for(j=0;j<128;j++) { OLED_Write_Data(0x00);//全部写零 } } } void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char) { uint8_t i; OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分 for (i = 0; i < 8; i++) { OLED_Write_Data(OLED_F8x16[Char - ' '][i]); //显示上半部分内容 } OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分 for (i = 0; i < 8; i++) { OLED_Write_Data(OLED_F8x16[Char - ' '][i + 8]); //显示下半部分内容 } } void OLED_ShowString(uint8_t Line, uint8_t Column, char *String) { uint8_t i; for (i = 0; String[i] != '\0'; i++) { OLED_ShowChar(Line, Column + i, String[i]); } } /** * @brief OLED次方函数 * @retval 返回值等于X的Y次方 */ uint32_t OLED_Pow(uint32_t X, uint32_t Y) { uint32_t Result = 1; while (Y--) { Result *= X; } return Result; } void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length) { uint8_t i; for (i = 0; i < Length; i++) { OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0'); } } void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length) { uint8_t i; uint32_t Number1; if (Number >= 0) { OLED_ShowChar(Line, Column, '+'); Number1 = Number; } else { OLED_ShowChar(Line, Column, '-'); Number1 = -Number; } for (i = 0; i < Length; i++) { OLED_ShowChar(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0'); } } void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length) { uint8_t i, SingleNumber; for (i = 0; i < Length; i++) { SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16; if (SingleNumber < 10) { OLED_ShowChar(Line, Column + i, SingleNumber + '0'); } else { OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A'); } } } void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length) { uint8_t i; for (i = 0; i < Length; i++) { OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0'); } } //OLED 显示开启函数 void OLED_Write_On(void){ OLED_Write_CMD(0X8D);//显示开启 OLED_Write_CMD(0X24);//开启电荷泵 OLED_Write_CMD(0XAF);//显示开启 } //OLED 显示关闭函数 void OLED_Write_Off(void){ OLED_Write_CMD(0X8D);//显示开启 OLED_Write_CMD(0X24);//开启电荷泵 OLED_Write_CMD(0XAE);//显示关闭 } void OLED_Write_Display(uint8_t x,uint8_t y,uint8_t g,uint8_t k,uint8_t *dat) { uint8_t i=0,j=0; for(i=0;i<g;i++) { OLED_Write_CMD((0XB0|i)+x); OLED_Write_CMD(0x10+(y>>4&0x0f)); OLED_Write_CMD(y&0x0f); for(j=0;j<k;j++) { OLED_Write_Data(*dat++); } } } void OLED_Refresh(void) { uint8_t i,n; for(i=0;i<8;i++) { OLED_Write_CMD(0xb0+i); //设置行起始地址 OLED_Write_CMD(0x00); //设置低列起始地址 OLED_Write_CMD(0x10); //设置高列起始地址 I2C_Start(); I2C_Write_Byte(0x78); I2C_Read_Ack(); I2C_Write_Byte(0x40); I2C_Read_Ack(); for(n=0;n<128;n++) { I2C_Write_Byte(OLED_GRAM[n][i]); I2C_Read_Ack(); } I2C_Stop(); } }

  1. key.c

 

#include "key.h" extern int i; uint32_t uwTick_Oled_Slow_Down=0; uint8_t ucKey_Val, unKey_Down, ucKey_Up, ucKey_Old; void Key_Proc(void) { //if((SysTick - uwTick_Key_Set_Point)<100) return;//减速函数 //uwTick_Key_Set_Point = SysTick; //delay1ms(1); ucKey_Val = Key_Scan(); unKey_Down = ucKey_Val & (ucKey_Old ^ ucKey_Val); ucKey_Up = ~ucKey_Val & (ucKey_Old ^ ucKey_Val); ucKey_Old = ucKey_Val; switch(unKey_Down) { case 1: PC13_TOG(); break; case 2: mode1(); break; case 3: mode2(); PC13_TOG(); break; case 4: mode3(); break; } } uint8_t Key_Scan(void) { //PB02_GETVALUE(); uint8_t unKey_Val = 0; if( GPIO_ReadPin(CW_GPIOB , GPIO_PIN_2 ) ) { PC13_SETLOW(); i=0; mode1(); } else { PC13_SETHIGH(); // unKey_Val = 2; unKey_Val ++; if(unKey_Val==4) { unKey_Val = 0;} } return unKey_Val; }

  1. duoji.c

 

#include "duoji.h" void ATIM(void) { ATIM_InitTypeDef ATIM_InitStruct;//定义结构体 ATIM_OCInitTypeDef ATIM_OCInitStruct; __disable_irq(); NVIC_EnableIRQ(ATIM_IRQn); //优先级,无优先级分组 __enable_irq(); ATIM_InitStruct.BufferState = DISABLE; /*!< ARR缓存失能 */ ATIM_InitStruct.ClockSelect = ATIM_CLOCK_PCLK; /*!< 计数时钟选择 */ ATIM_InitStruct.CounterAlignedMode = ATIM_COUNT_MODE_EDGE_ALIGN; /*!< 计数对齐模式: 边沿 */ ATIM_InitStruct.CounterDirection = ATIM_COUNTING_UP; /*!< 计数方向 */ ATIM_InitStruct.CounterOPMode = ATIM_OP_MODE_REPETITIVE; /*!< 运行模式:重复 */ ATIM_InitStruct.OverFlowMask = DISABLE; /*!< 重复计数器上溢出不屏蔽 */ ATIM_InitStruct.Prescaler = ATIM_Prescaler_DIV64; // 计数时钟1MHz ATIM_InitStruct.ReloadValue = 19999; // 溢出周期20ms /*!< ARR赋值 ATIM_InitStruct.RepetitionCounter = 0; /*!< 重复周期计数值,RCR寄存器 */ ATIM_InitStruct.UnderFlowMask = DISABLE;/*!< 重复计数下溢出不屏蔽 */ ATIM_Init(&ATIM_InitStruct);//初始化 ATIM_OCInitStruct.BufferState = ENABLE; /*!< 比较缓存使能状态 */ ATIM_OCInitStruct.OCDMAState = DISABLE; /*!< 比较匹配触发DMA使能状态 */ ATIM_OCInitStruct.OCInterruptSelect = ATIM_OC_IT_UP_COUNTER; ATIM_OCInitStruct.OCInterruptState = ENABLE;/*!< 比较匹配触发中断使能状态 */ ATIM_OCInitStruct.OCMode = ATIM_OCMODE_PWM1;/*!< 比较模式配置 */ ATIM_OCInitStruct.OCPolarity = ATIM_OCPOLARITY_NONINVERT;/*!< 端口极性选择:正向 */ ATIM_OC2BInit(&ATIM_OCInitStruct);//初始化 ATIM_OCInitStruct.BufferState = ENABLE; ATIM_OCInitStruct.OCDMAState = DISABLE; ATIM_OCInitStruct.OCInterruptSelect = ATIM_OC_IT_UP_COUNTER; ATIM_OCInitStruct.OCInterruptState = ENABLE; ATIM_OCInitStruct.OCMode = ATIM_OCMODE_PWM1; ATIM_OCInitStruct.OCPolarity = ATIM_OCPOLARITY_NONINVERT; ATIM_OC1BInit(&ATIM_OCInitStruct); ATIM_ITConfig(ATIM_CR_IT_OVE, ENABLE);//使能溢出中断 ATIM_CH2Config(ATIM_CHxB_CIE, ENABLE);//2通道使能 ATIM_CH1Config(ATIM_CHxB_CIE, ENABLE);//1通道使能 ATIM_Cmd(ENABLE);//高级定时器启动 ATIM_CtrlPWMOutputs(ENABLE);//pwm输出启动 } void ATIM_IRQHandlerCallBack(void)//高级定时器中断处理回调函数 { if (ATIM_GetITStatus(ATIM_IT_OVF))//获取ATIM中断标志位 即溢出 { ATIM_ClearITPendingBit(ATIM_IT_OVF);//清除ATIM中断标志位 即归零 if (ATIM_GetITStatus(ATIM_IT_C2BF))//通道 CH2B 比较匹配标志中断 { ATIM_ClearITPendingBit(ATIM_IT_C2BF);//清除ATIM中断标志位 } if (ATIM_GetITStatus(ATIM_IT_C1BF)) { ATIM_ClearITPendingBit(ATIM_IT_C1BF); } } }

  1. openmv.c

 

#include "openmv.h" #define BAUD_RATE 115200 /** * @brief 配置UART * */ void UART_Configuration(void) { __RCC_GPIOA_CLK_ENABLE(); __RCC_UART3_CLK_ENABLE(); PA02_AFx_UART3TXD(); PA03_AFx_UART3RXD(); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Pins = GPIO_PIN_2; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; GPIO_Init(CW_GPIOA, &GPIO_InitStructure); GPIO_InitStructure.Pins = GPIO_PIN_3; GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP; GPIO_Init(CW_GPIOA, &GPIO_InitStructure); USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = BAUD_RATE; USART_InitStructure.USART_Over = USART_Over_16; USART_InitStructure.USART_Source = USART_Source_PCLK; USART_InitStructure.USART_UclkFreq = RCC_Sysctrl_GetHClkFreq(); USART_InitStructure.USART_StartBit = USART_StartBit_FE; 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(CW_UART3, &USART_InitStructure); //开启串口中断 NVIC_SetPriority(UART3_IRQn, 0); NVIC_EnableIRQ(UART3_IRQn); //开启接收中断 USART_ITConfig(CW_UART3, USART_IT_RC, ENABLE); //开启接收中断 }

8.1.6mode.c

 

#include "mode.h" extern int b1 ,b2,mode,chang,kuan,pianyiliang; extern int ax,sx,dx,fx,ay,sy,dy,fy; extern int ax1,sx1,dx1,fx1,ay1,sy1,dy1,fy1; void mode1(void) { ATIM_SetCompare1B(b1);//占空比初始化90度上 ATIM_SetCompare2B(b2);//占空比初始化90度下 mode=1;//模式更变 } void mode2(void) { mode=2;//模式更变 x是0.5正方形对应的占空比 int g=100,n=5,x=158;//时间间隔ms为单位//n是调一个时间间隔走多少 int p=1,y; if(p==1) { ATIM_SetCompare2B(b2+x); delay1ms(g); if(y<11) { ATIM_SetCompare2B(b2+x); ATIM_SetCompare1B(b1+x-x*y/10); y++;delay1ms(g); } p+=1; }y=n; if(p==2) { ATIM_SetCompare2B(b2+x); delay1ms(g); if(y<11) { ATIM_SetCompare2B(b2+x); ATIM_SetCompare1B(b1-x*y/10); y++;delay1ms(g); } p+=1; }y=n; if(p==3) { ATIM_SetCompare1B(b1-x); delay1ms(g); if(y<11) { ATIM_SetCompare1B(b1-x); ATIM_SetCompare2B(b2+x-x*y/10); y++;delay1ms(g); } p+=1; }y=n; if(p==4) { ATIM_SetCompare1B(b1-x); delay1ms(g); if(y<11) { ATIM_SetCompare1B(b1-x); ATIM_SetCompare2B(b2-x*y/10); y++;delay1ms(g); } p+=1; }y=n; if(p==5) { ATIM_SetCompare2B(b2-x); delay1ms(g); if(y<11) { ATIM_SetCompare2B(b2-x); ATIM_SetCompare1B(b1-x+x*y/10); y++;delay1ms(g); } p+=1; }y=n; if(p==6) { ATIM_SetCompare2B(b2-x); delay1ms(g); if(y<11) { ATIM_SetCompare2B(b2-x); ATIM_SetCompare1B(b1+x*y/10); y++;delay1ms(g); } p+=1; }y=n; if(p==7) { ATIM_SetCompare1B(b1+x); delay1ms(g); if(y<11) { ATIM_SetCompare1B(b1+x); ATIM_SetCompare2B(b2-x+x*y/10); y++;delay1ms(g); } p+=1; }y=n; if(p==8) { ATIM_SetCompare1B(b1+x); delay1ms(g); if(y<11) { ATIM_SetCompare1B(b1+x); ATIM_SetCompare2B(b2+x*y/10); y++;delay1ms(g); } p=1; }y=n; } void mode3()//围绕着原点中心 { mode=3;//模式更变 kuan=(chang*21)/30; ATIM_SetCompare1B(b1+chang);//向右减 delay1ms(10); ATIM_SetCompare2B(b2+kuan);//向上加 暂定左上点 delay1ms(1000); ATIM_SetCompare1B(b1-chang);//向右减 delay1ms(10); ATIM_SetCompare2B(b2+kuan);//向上加 暂定右上点 delay1ms(1000); ATIM_SetCompare1B(b1-chang);//向右减 delay1ms(10); ATIM_SetCompare2B(b2-kuan);//向上加 暂定右下点 delay1ms(1000); ATIM_SetCompare1B(b1+chang);//向右减 delay1ms(10); ATIM_SetCompare2B(b2-kuan);//向上加 暂定左下 delay1ms(1000); } void mode4() { mode=4; delay1ms(10); ATIM_SetCompare1B(b1+chang+(ax1-ax)*chang*2/pianyiliang);//向右减 delay1ms(10); ATIM_SetCompare2B(b2+kuan+(ay1-ay)*chang*2/pianyiliang);//向上加 暂定左上点 delay1ms(1000); ATIM_SetCompare1B(b1-chang+(sx1-sx)*chang*2/pianyiliang);//向右减 delay1ms(10); ATIM_SetCompare2B(b2+kuan+(sy1-sy)*chang*2/pianyiliang);//向上加 暂定右上点 delay1ms(1000); ATIM_SetCompare1B(b1-chang+(dx1-dx)*chang*2/pianyiliang);//向右减 delay1ms(10); ATIM_SetCompare2B(b2-kuan+(dy1-dy)*chang*2/pianyiliang);//向上加 暂定右下点 delay1ms(1000); ATIM_SetCompare1B(b1+chang+(fx1-fx)*chang*2/pianyiliang);//向右减 delay1ms(10); ATIM_SetCompare2B(b2-kuan+(fy1-fy)*chang*2/pianyiliang);//向上加 暂定左下 delay1ms(1000); }

8.1.7 main.c

 

#include "main.h" // Device header void GPIO_Configuration(void); void RCC_Configuration(void); void UART_Configuration(void); void NVIC_Configuration(void);//配置中断 int b1=1300,b2=1600;//yusndianzuobiao原点变量 int mode=0;//模式选择 int chang=80,kuan; //A4纸相对原点的方向占空比 chang代表的是左右占空比变量 宽代表的上下占空比 int pianyiliang=0; int ax,sx,dx,fx,ay,sy,dy,fy; int ax1,sx1,dx1,fx1,ay1,sy1,dy1,fy1; int i=1; int chushi=0; int main() { RCC_Configuration(); UART_Configuration(); GPIO_Configuration(); ATIM(); NVIC_Configuration(); mode1(); //mode2(); while(1) { Key_Proc(); } } void RCC_Configuration(void) { //...........................64M // 0. HSI使能并校准 RCC_HSI_Enable(RCC_HSIOSC_DIV6); // 1. 设置HCLK和PCLK的分频系数  RCC_HCLKPRS_Config(RCC_HCLK_DIV1); RCC_PCLKPRS_Config(RCC_PCLK_DIV1); // 2. 使能PLL,通过PLL倍频到64MHz RCC_PLL_Enable(RCC_PLLSOURCE_HSI, 8000000, 8); // HSI 默认输出频率8MHz ///< 当使用的时钟源HCLK大于24M,小于等于48MHz:设置FLASH 读等待周期为2 cycle ///< 当使用的时钟源HCLK大于48MHz:设置FLASH 读等待周期为3 cycle __RCC_GPIOB_CLK_ENABLE();//使能gpio b时钟 __RCC_FLASH_CLK_ENABLE(); FLASH_SetLatency(FLASH_Latency_3); // 3. 时钟切换到PLL RCC_SysClk_Switch(RCC_SYSCLKSRC_PLL); RCC_SystemCoreClockUpdate(64000000); //.............................. __RCC_ATIM_CLK_ENABLE();//使能高级定时器时钟 } void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStruct; __RCC_GPIOA_CLK_ENABLE(); __RCC_GPIOB_CLK_ENABLE(); __RCC_GPIOC_CLK_ENABLE(); GPIO_InitStruct.IT = GPIO_IT_NONE; //KEY1 KEY2 GPIO_InitStruct.Mode = GPIO_MODE_INPUT_PULLDOWN; GPIO_InitStruct.Pins = GPIO_PIN_2; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_Init(CW_GPIOB, &GPIO_InitStruct); GPIO_InitStruct.IT = GPIO_IT_NONE; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//上拉输出 GPIO_InitStruct.Pins = GPIO_PIN_13| GPIO_PIN_14; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;//高速 PB13_AFx_ATIMCH1B(); PB14_AFx_ATIMCH2B();//PB14复用高级定时器2通道 GPIO_Init(CW_GPIOB, &GPIO_InitStruct); GPIO_InitStruct.IT = GPIO_IT_NONE; //LED1 LED2 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pins = GPIO_PIN_13; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_Init(CW_GPIOC, &GPIO_InitStruct); } void NVIC_Configuration(void)//配置中断 { } void UART3_IRQHandler(void) { /* USER CODE BEGIN */ uint8_t TxRxBuffer; uint8_t i; static uint8_t RxCounter1=0; static uint16_t RxBuffer1[16]={0}; static uint8_t RxState = 0; static uint8_t RxFlag1 = 0; //OLED_ShowHexNum(3, 1, 0xAA55, 4); if(USART_GetITStatus(CW_UART3, USART_IT_RC) != RESET) { USART_ClearITPendingBit(CW_UART3, USART_IT_RC); //清除中断标志位 TxRxBuffer = USART_ReceiveData_8bit(CW_UART3); // USART_SendData_8bit(CW_UART1, TxRxBuffer); //GPIO_WritePin(LED_GPIO_PORT, LED_GPIO_PINS, GPIO_Pin_SET); if(RxState==0&&TxRxBuffer==0x2C) //0x2c帧头 { RxState=1; RxBuffer1[RxCounter1++]=TxRxBuffer; OLED_Write_On(); } else if(RxState==1&&TxRxBuffer==0x12) //0x12帧头 { RxState=2; RxBuffer1[RxCounter1++]=TxRxBuffer; } else if(RxState==2) { RxBuffer1[RxCounter1++]=TxRxBuffer; if(RxCounter1>=15||TxRxBuffer== 0x5B) //RxBuffer1接受满了,接收数据结束 { RxState=3; RxFlag1=1; Cx1=RxBuffer1[RxCounter1-9]; Cy1=RxBuffer1[RxCounter1-8]; Cx2=RxBuffer1[RxCounter1-7]; Cy2=RxBuffer1[RxCounter1-6]; Cx3=RxBuffer1[RxCounter1-5]; Cy3=RxBuffer1[RxCounter1-4]; Cx4=RxBuffer1[RxCounter1-3]; Cy4=RxBuffer1[RxCounter1-2]; } } else if(RxState==3) //检测是否接受到结束标志 { if(RxBuffer1[RxCounter1-1] == 0x5B) { USART_ITConfig(CW_UART3,USART_IT_RC,DISABLE);//关闭DTSABLE中断 if(RxFlag1) { ax1=Cx1;sx1=Cx2;dx1=Cx3;fx1=Cx4;ay1=Cy1;sy1=Cy2;dy1=Cy3;fy1=Cy4; yiliang=(Cx2-Cx1); OLED_Write_On(); OLED_ShowNum(1,1,Cx1,3);OLED_ShowNum(1,5,Cy1,3); OLED_ShowNum(2,17,Cx2,3); OLED_ShowNum(2,22,Cy2,3); } } RxFlag1 = 0; RxCounter1 = 0; RxState = 0; USART_ITConfig(CW_UART3,USART_IT_RC,ENABLE); } else //接收错误 { RxState = 0; RxCounter1=0; for(i=0;i<10;i++) { RxBuffer1[i]=0x00; //将存放数据数组清零 } } } else //接收异常 { RxState = 0; RxCounter1=0; for(i=0;i<10;i++) { RxBuffer1[i]=0x00; //将存放数据数组清零 } } }

  1. 比赛过程及经验总结CW32E题开源

9.1 赛前准备环节

全国大学生电子设计竞赛赛题会在比赛第一天公布,参赛选手必须在赛题发布前根据大纲先行准备元器件和工具,等待赛题发布当天及时进行采购,并且在比赛前一定要有充分的准备关于硬件和软件的学习。

在正式参赛之前我们参赛选手需要熟练掌握C语言的使用以及一些主控的使用,可以适当进行主控功能的研究,同时参赛选手也应该具备电路和焊接能力,以免比赛期间遇到难题,并且我们可以在网上进行浏览电赛信息,及时关注电赛官网信息,也可以观看相关视频来提升自身能力。

其次就是队员的分工,电赛是三人一组,一般就是一个人写程序两个人调电路。这里面给大家的经验是写程序的人最好也懂一些硬件,而且如果题目太难的话需要写软件的人来帮忙一起调电路。要保证电路的稳定,用代码解决是最好的方式,代码一般时候不会出现问题,电路的稳定十分重要,我们在测试时在这个问题上卡了将近一天没有进展。

元器件选择,在比赛之前就应当进行元器件的选购,一般可以按照大赛给出的材料表进行购买,我们队伍主要先购买了主控,稳压以及openmv等一些元器件,如果在比赛期间发现元器件缺少一定要及时购买,网购一定要加急。

9.2 比赛过程

全国大学生电子设计大赛赛题通常在早晨七点至八点间公布,比赛前一天晚上,由队长提醒队员保持充足的休息,为接下来的高强度比赛养精蓄锐。 第一天 等待赛题发布之后,首先由各队员审题,然后由指导老师主持组内讨论各类题型的核心问题以及解题过程可能出现的突发问题,最终结合赛题难度最终确定E题。之后由队长结合个人能力确定组内分工:两个编程手和一个硬件手。下面由硬件手主持再次进行组内讨论,对E题进行详细讨论,最终确定元器件的选型,当天上午展示v确定使用OpenMv作为视觉模块,主控芯片选用CW32F030,以MG995舵机结合机械结构搭建二维云台并搭载激光笔。但是同时也是用stm32同时开发,决定第二天讨论具体使用型号。

第二天:通过第一天的激烈讨论,以及结合我们队员情况,我们在比赛中果断的选择了CW32F030芯片作为主控MCU,在比赛之前,我们队员就已经充分了解此芯片的结构和使用,另外在摄像头方面我们选择的是OpenMV为视觉识别模块,以MG995舵机搭建二维简易云台搭载激光笔,接着进行编写部分程序代码。

第三天:经过前两天的铺垫,在第三天我们基本已经有了大致的方向去攻克这个难题,并且已经大致调试出来部分功能,但是由于比赛存在精度要求比较高,所以我们将已经写好的程序继续调试,没有写好的功能继续添加,在精确误差的同时进行新功能的实现。在此同时,我们也开始了资料的整理以及报告的撰写和测试。

第四天:通过前三天的努力,已经将实现的功能误差调整到比赛误差标准之中,所以此时我们进行了脱机测试以确保已经做好的功能可以脱机运转,同时我们也抓紧最后一天的时间去突破后续的功能,同时我们的报告进度也在紧跟我们比赛的进程,在反复的进行脱机测试后,并确定封箱器件后进行了作品和个人资料的封箱。

  • 经历

在比赛期间我们在电源方面的功课做的不足,以至于经常因为电压的不稳定而导致云台的精确程度不够。

第二脱机运行方面,我们在脱机运行这个环节考虑不周,没有将电压,电流考虑到位,导致在比赛期间云台的=运转出现卡死的结果。

 

这篇关于2023年电赛cw32分享的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/835427

相关文章

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

java常用面试题-基础知识分享

什么是Java? Java是一种高级编程语言,旨在提供跨平台的解决方案。它是一种面向对象的语言,具有简单、结构化、可移植、可靠、安全等特点。 Java的主要特点是什么? Java的主要特点包括: 简单性:Java的语法相对简单,易于学习和使用。面向对象:Java是一种完全面向对象的语言,支持封装、继承和多态。跨平台性:Java的程序可以在不同的操作系统上运行,称为"Write once,

分享5款免费录屏的工具,搞定网课不怕错过!

虽然现在学生们不怎么上网课, 但是对于上班族或者是没有办法到学校参加课程的人来说,网课还是很重要的,今天,我就来跟大家分享一下我用过的几款录屏软件=,看看它们在录制网课时的表现如何。 福昕录屏大师 网址:https://www.foxitsoftware.cn/REC/ 这款软件给我的第一印象就是界面简洁,操作起来很直观。它支持全屏录制,也支持区域录制,这对于我这种需要同时录制PPT和老师讲

HNU-2023电路与电子学-实验3

写在前面: 一、实验目的 1.了解简易模型机的内部结构和工作原理。 2.分析模型机的功能,设计 8 重 3-1 多路复用器。 3.分析模型机的功能,设计 8 重 2-1 多路复用器。 4.分析模型机的工作原理,设计模型机控制信号产生逻辑。 二、实验内容 1.用 VERILOG 语言设计模型机的 8 重 3-1 多路复用器; 2.用 VERILOG 语言设计模型机的 8 重 2-1 多

【干货分享】基于SSM的体育场管理系统的开题报告(附源码下载地址)

中秋送好礼 中秋佳节将至,祝福大家中秋快乐,阖家幸福。本期免费分享毕业设计作品:《基于SSM的体育场管理系统》。 基于SSM的体育场管理系统的开题报告 一、课题背景与意义 随着全民健身理念的深入人心,体育场已成为广大师生和社区居民进行体育锻炼的重要场所。然而,传统的体育场管理方式存在诸多问题,如资源分配不均、预约流程繁琐、数据统计不准确等,严重影响了体育场的使用效率和用户体验。

图书管理系统系统分享

分享一个图书管理系统,Java、SpringBoot、Vue和MySQL开发的图书馆管理系统 gitee项目地址:https://gitee.com/yuanmomoya/open-source-project/tree/master/books-management-system GitHub项目地址:https://github.com/yuanmomoya/open-source-pro

站长常用Shell脚本整理分享(全)

站长常用Shell脚本整理分享 站长常用Shell脚本整理分享1-10 站长常用Shell脚本整理分享11-20 站长常用Shell脚本整理分享21-30 站长常用Shell脚本整理分享31-40 站长常用Shell脚本整理分享41-50 站长常用Shell脚本整理分享51-59 长期更新

分享MSSQL、MySql、Oracle的大数据批量导入方法及编程手法细节

1:MSSQL SQL语法篇: BULK INSERT      [ database_name . [ schema_name ] . | schema_name . ] [ table_name | view_name ]         FROM 'data_file'        [ WITH       (      [ [ , ] BATCHSIZE = batch_siz