- 2024-12-15
-
发表了主题帖:
【极海APM32M3514电机通用评估板】基于DMA的多通道ADC转换测试
由于该MCU和开发板主要针对电机,所以ADC的数据采集也是针对电机的数据进行采集,针对BLDC电机驱动,需要我们实时采集各项电流,电压,并对电流的过流,电压的欠压,过压进行判断,同时还需要电源电压,电机调速电位器等模拟量进行采集。
1.电机通用评估板的ADC采样电路如下:
1.1.电机三相IV,IU,IW电压采集电路,通过电阻分压,并使用稳压管进行I/O过压保护。
1.2.电机三相电流和总电流采集电路,通过APM32M3514自带的运算放大器进行放大,该示例中选用外部放大电阻。并通过一个运算放大器提供1.65V的参考电压。
1.3.输入电压和电阻可调旋钮的采集电路,
2.APM32M3514 MCU使用的ADC硬件电路使用通道介绍
2.1.电机三相电压采集ADC引脚,使用通道ADC_IN13,ADC_IN14,ADC_IN15,分别采集V,U,W三相。
1.2.PA0是采集参考电压,目前未使用,PA4,PB0和PB10分别采集IV相电流,IU相电流和ISUM总电流,
2.3.PA6用于采集输入电压,PA7用于采集可变电阻调节旋钮阻值变化
3.代码展示和讲解
3.1.ADC的IO及通道初始化
void Drv_Adc_Init(void)
{
ADC_Config_T ADC_InitStructure;
//ADC DMA Initial
DMA_Config_T DMA_InitStructure;
DMA_InitStructure.peripheralAddress = (uint32_t)&(ADC->DATA);//ADC地址
DMA_InitStructure.memoryAddress = (uint32_t)&ADC_ConvertedValue[0]; //内存地址
DMA_InitStructure.direction = DMA_DIR_PERIPHERAL; //方向(从外设到内存)
DMA_InitStructure.bufferSize = TOTAL_CHANNEL;//TOTAL_CHANNEL; //传输内容的大小---传输次数
DMA_InitStructure.peripheralInc = DMA_PERIPHERAL_INC_DISABLE; //外设地址固定
DMA_InitStructure.memoryInc = DMA_MEMORY_INC_ENABLE;//DMA_MEMORY_INC_ENABLE; //内存地址固定
DMA_InitStructure.peripheralDataSize = DMA_PERIPHERAL_DATASIZE_HALFWORD ; //外设数据单位
DMA_InitStructure.memoryDataSize = DMA_MEMORY_DATASIZE_HALFWORD ; //内存数据单位
DMA_InitStructure.circular = DMA_CIRCULAR_ENABLE ; //DMA模式:循环传输
DMA_InitStructure.priority = DMA_PRIORITY_LEVEL_VERYHIGH ; //优先级:高
DMA_InitStructure.memoryTomemory = DMA_M2M_DISABLE; //禁止内存到内存的传输
ADC_Reset();
DMA_Config(DMA_CHANNEL_1, &DMA_InitStructure); //配置DMA的1通道
DMA_Enable(DMA_CHANNEL_1);
ADC_ClockMode(ADC_CLOCK_MODE_ASYNCLK);//48M/4=12mADC_CLOCK_MODE_SYNCLKDIV4
/* Enable ADC clock */
// RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC);
ADC_ConfigStructInit(&ADC_InitStructure);
ADC_InitStructure.convMode = ADC_CONVERSION_SINGLE;
ADC_InitStructure.scanDir = ADC_SCAN_DIR_UPWARD;
ADC_InitStructure.extTrigConv1 = ADC_EXT_TRIG_CONV_TRG1; // timer1 CC4
ADC_InitStructure.extTrigEdge1 = ADC_EXT_TRIG_EDGE_RISING;
ADC_InitStructure.dataAlign = ADC_DATA_ALIGN_RIGHT;
ADC_InitStructure.resolution = ADC_RESOLUTION_12B;
ADC_Config(&ADC_InitStructure);
ADC_ConfigChannel(ADC_CHANNEL_2 | ADC_CHANNEL_8 | ADC_CHANNEL_6 | ADC_CHANNEL_7| ADC_CHANNEL_12| ADC_CHANNEL_13| ADC_CHANNEL_14| ADC_CHANNEL_15 ,ADC_SAMPLE_TIME_1_5);
ADC->CFG1_B.OVRMAG = 1;
ADC_EnableInterrupt(ADC_INT_CS);
//=========================ADC中断使用=================================================
NVIC_EnableIRQ(ADC_COMP_IRQn);//
NVIC_SetPriority(ADC_COMP_IRQn,0);
ADC_DMARequestMode(ADC_DMA_MODE_CIRCULAR);
ADC_EnableDMA();
ADC_Enable();
ADC_StartConversion();//必需要启动一下
/* Config ADC Channel GPIO */
GPIO_Config_T GPIO_InitStructure;
GPIO_InitStructure.pin = GPIO_Pin_ADC_VDC;//pin
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;//GPIO speed
GPIO_InitStructure.mode = GPIO_MODE_AN;//GPIO configured as analog input
GPIO_InitStructure.pupd = GPIO_PUPD_NO;//no pull-up and pull-down
GPIO_Config(GPIO_ADC_VDC, &GPIO_InitStructure);
GPIO_InitStructure.pin = GPIO_Pin_ADC_Handle;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_Config(GPIO_ADC_Handle, &GPIO_InitStructure);
GPIO_InitStructure.pin = GPIO_Pin_ADC_IU;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_Config(GPIO_ADC_IU, &GPIO_InitStructure);
GPIO_InitStructure.pin = GPIO_Pin_ADC_IV;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_Config(GPIO_ADC_IV, &GPIO_InitStructure);
GPIO_InitStructure.pin = GPIO_Pin_ADC_IBUS;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_Config(GPIO_ADC_IBUS, &GPIO_InitStructure);
GPIO_InitStructure.pin = GPIO_Pin_ADC_UV;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_Config(GPIO_ADC_UV, &GPIO_InitStructure);
GPIO_InitStructure.pin = GPIO_Pin_ADC_VV;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_Config(GPIO_ADC_VV, &GPIO_InitStructure);
GPIO_InitStructure.pin = GPIO_Pin_ADC_WV;
GPIO_InitStructure.speed = GPIO_SPEED_50MHz;
GPIO_InitStructure.mode = GPIO_MODE_AN;
GPIO_InitStructure.pupd = GPIO_PUPD_NO;
GPIO_Config(GPIO_ADC_WV, &GPIO_InitStructure);
}
3.2.启动ADC转换
/* Wait until ADC is ready 等待ADC准备好*/
while (!ADC_ReadStatusFlag(ADC_FLAG_ADRDY));
ADC_StartConversion();//开启ADC转换
__enable_irq(); //Enable all interrupts
3.3.ADC中断
当产生中断时,读取ADC的转换结果,并将之保存,注意转换结果是按通道顺序排列。
uint16_t chnlvcur[50] = {0};
uint16_t chnlucur[50] = {0};
uint16_t chnlibus[50] = {0};
uint16_t chnluvol[50] = {0};
uint16_t chnlvvol[50] = {0};
uint16_t chnlwvol[50] = {0};
uint16_t chnlsvol[50] = {0};
uint16_t chnlinvol[50] = {0};
uint16_t i = 0;
void ADC_COMP_IRQHandler(void)
{
chnlvcur = (int16_t)ADC_GetValue(CURR_CHANNEL_V);
chnlucur = (int16_t)ADC_GetValue(CURR_CHANNEL_U);
chnlibus = (int16_t)ADC_GetValue(IBUS_CHANNEL);
chnlsvol = (int16_t)ADC_GetValue(Handle_CHANNEL);
chnlinvol = (int16_t)ADC_GetValue(VDC_CHANNEL);
chnluvol = (int16_t)ADC_GetValue(VOL_CHANNEL_U);
chnlvvol = (int16_t)ADC_GetValue(VOL_CHANNEL_V);
chnlwvol = (int16_t)ADC_GetValue(VOL_CHANNEL_W);
i++;
if(i>= 50)
{
i = 0;
}
}
}
4.代码运行结果查看
6.测试情况及数据
以下表电机工作时和不工作时,ADC采集的电压值作为比较,发现电机不工作时,这时电流波动较小,电压采集结果稳定,误差小。而在电机工作时,发现偶尔会出现电压值偏差很大,并且是正偏或负偏很大的值都偶尔出现,通过该测试可以发现,我们ADC在面对电流变化复杂的情况,不仅软件需要做滤波,硬件也需要处理好电源的突然变化。针对该评估板对动态输入电压对ADC的影响,可以每十组数据,去掉最大值和最小值,进行均值滤波,就可以将这种现象带来的误差减小到最小。
序号
输入电压(电机工作)
输入电压(电机不工作)
0
1360
1358
1
1352
1359
2
1362
1361
3
1361
1358
4
1361
1358
5
1361
1358
6
1355
1358
7
1359
1358
8
1360
1358
9
1361
1358
10
1361
1359
11
1360
1358
12
1525
1359
13
1348
1358
14
1367
1359
15
1358
1358
16
1371
1359
17
1752
1358
18
1328
1358
19
1361
1359
20
1360
1359
21
1361
1359
22
1361
1358
23
1359
1358
24
1399
1359
25
1361
1358
26
1361
1358
27
1361
1358
28
1360
1359
29
1360
1359
30
1361
1358
31
1361
1358
32
1361
1358
33
1361
1358
34
1120
1359
35
1359
1358
36
1356
1358
37
1363
1358
38
1347
1358
39
1247
1358
40
1715
1359
41
1198
1359
42
1361
1359
43
1361
1358
44
1361
1358
45
1361
1359
46
1357
1358
47
1362
1358
48
1361
1358
49
1361
1359
7.综合评价
通过这次测试,可以看出该芯片的ADC精度高,采样时间和采集值都表现不错。
- 2024-12-09
-
回复了主题帖:
极海APM32M3514串口使用PF0和PF1问题
IllusionXX 发表于 2024-12-9 10:51
电机开发板PF0和PF1接的是晶振,你这样可不得跑飞吗,看了一下官方就没有留出打印口,那我想知道测试总要打 ...
用内部晶振,他们CASE使用了串口,应该切换到内部晶振,
-
回复了主题帖:
极海APM32M3514串口使用PF0和PF1问题
不说我还真没有发现PF0,PF1接的晶振,那串口就没有使用了,我看PA2,PA3,PA9和PA10都已经被使用了,看到CH340上接的PF0和PF1,还跑去把引脚配置后,就跑飞了。那要用串口只能使用内部晶振了!
不过这硬件设计有点新颖。
让我措手不及了
谢谢各位了
- 2024-12-08
-
发表了主题帖:
极海APM32M3514串口使用PF0和PF1问题
各位高手及极海的FAE,我在使用极海的APM32M3514串口时遇到如下问题,
我使用的板子根据硬件电路将串口的引脚改为PF0和PF1的串口时,开启中串口中断,代码跑飞,引脚配置如下:
在初始化代码中,只要把串口1中断打开,程序跑飞,使用的是COM1 初始化如下:
void APM_MINI_COMInit(COM_T COM)
{
GPIO_Config_T gpioConfig;
USART_Config_T usartConfigStruct;
/* Enable GPIO clock */
RCM_EnableAHBPeriphClock(COM_TX_PORT_CLK[COM] | COM_RX_PORT_CLK[COM]);
/* Enable COM1 or COM2 clock */
if (COM == COM1)
{
RCM_EnableAPB2PeriphClock(COM_USART_CLK[COM]);
}
else
{
RCM_EnableAPB1PeriphClock(COM_USART_CLK[COM]);
}
/* Connect PXx to USARTx_Tx */
GPIO_ConfigPinAF(COM_TX_PORT[COM], COM_TX_PIN_SOURCE[COM], COM_TX_AF[COM]);
/* Connect PXx to USARTx_Rx */
GPIO_ConfigPinAF(COM_RX_PORT[COM], COM_RX_PIN_SOURCE[COM], COM_RX_AF[COM]);
/* Configure USART Tx as alternate function push-pull */
gpioConfig.mode = GPIO_MODE_AF;
gpioConfig.pin = COM_TX_PIN[COM];
gpioConfig.speed = GPIO_SPEED_50MHz;
gpioConfig.outtype = GPIO_OUT_TYPE_PP;
gpioConfig.pupd = GPIO_PUPD_PU;
GPIO_Config(COM_TX_PORT[COM], &gpioConfig);
/* Configure USART Rx as input floating */
gpioConfig.pin = COM_RX_PIN[COM];
GPIO_Config(COM_RX_PORT[COM], &gpioConfig);
/* MINI_USARTs configured as follow:
- BaudRate = 115200 baud
- Word Length = 8 Bits
- One Stop Bit
- No parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
*/
usartConfigStruct.baudRate = 115200;
usartConfigStruct.mode = USART_MODE_TX_RX;
usartConfigStruct.hardwareFlowCtrl = USART_FLOW_CTRL_NONE;
usartConfigStruct.parity = USART_PARITY_NONE;
usartConfigStruct.stopBits = USART_STOP_BIT_1;
usartConfigStruct.wordLength = USART_WORD_LEN_8B;
USART_Config(COM_USART[COM], &usartConfigStruct);
/* Enable USART_Interrupt_RXBNEIE */
USART_EnableInterrupt(COM_USART[COM], USART_INT_RXBNEIE);
if (COM_USART[COM] == USART1)
{
NVIC_EnableIRQRequest(USART1_IRQn, 2);
}
else if (COM_USART[COM] == USART2)
{
NVIC_EnableIRQRequest(USART2_IRQn, 3);
}
/* Enable USART */
// USART_Enable(USART1);
USART_Enable(COM_USART[COM]);
}
出错时调试报错如下:
请问一下谁知道这是什么原因
- 2024-12-07
-
发表了主题帖:
【极海APM32M3514电机通用评估板】开箱体验及环境搭建
本帖最后由 lang518899 于 2024-12-7 17:39 编辑
首先谢谢EEWORLD给予的BLDC无刷电机学习机会。
1.开发板及芯片简介
首先介绍一下极海APM32M3514芯片,该芯片是极海半导体针对电机控制推出的专用芯片,芯片采用32位的Arm Cortex-M0内核,最高72MHz工作频率支持单周期32位硬件乘法器,并封装了M0CP协处理器,可以实现硬件移位单元,32bit/32bit 除法器,可选带和的乘加运算,开方,三角函数,SVPWM等,64KbFlash和10KB SRAM(8+2(协处理器))一个12位13通道的ADC,一个16位高级定器器等等。
本次测试是极海基于APM32M3514芯片的开发板,外部有一个BLDC电机接口,一个24V供电接口,一个霍尔传感器接口,一个USB转串口,另外一个电位器,用于调节电机转速,一个正反转开关,一个Break开关,一个Fault指示灯。
收到包装如下图所示:
开发板正面图,可以看到绿色的电源接口,BLDC 电机接口,霍尔传感器接口,USB,电位器和切换开关等
背面只能看到走线,没有放置任何元器件
如下图所示,可以清晰的看到主控芯片的型号
2.测试环境搭建
由于很早准备了BLDC电机,我的电机型号是时代超群的57BL75S10,该电机支持24V,3000转,100W功率,带霍尔转感器,在收到开发板后,发现开发板的霍尔传感器接口,只支持3.3V,而我买的电机霍尔传感器接口是5V,很担心不能使用,于是查看芯片手册,发现霍尔传感器信号输入GPIO支持5V,那完全没有问题,环境搭好后,如下图所示:
如上图所示,将电机的U,V,W分别接到开发板的BLDC接口的U,V,W相上,再将霍尔传感器的Hu,Hv,Hw和GND分别与开发板的霍尔传感器接口相连接,由于板子没有5V,故我将5V接到仿真器的5V,供电24V后,整个电机测试环境搭好。
3.软件环境搭建:
3.1.在极海的官司网https://www.geehy.com/design/software,下载红色框中的SDK和Keil开发环境的pack包,
3.2.安装完成后,打开SDK包,如下图所示,由于Demo的LED灯引脚与PCB图不一致,需要我们更改GPIO引脚,更改后编译,下载
3.3.下载GPIO代码后,可以看到板上Fault灯,一闪一闪,
由于无法上传视频,就忽略
4.至此环境搭建完成,下面开始一步一步的测试。
-
发表了日志:
【极海APM32M3514电机通用评估板】开箱体验及环境搭建
- 2024-11-27
-
回复了主题帖:
测评入围名单:极海APM32M3514电机通用评估板
个人信息无误,确认可以完成测评分享计划
- 2024-11-14
-
回复了主题帖:
知识拆出来!EEWorld邀你来拆解(第16期)来啦~~~
很早以前做过车窗升降器,现在也在从事汽车电子嵌入式软件,对软硬件也熟悉,所以想参与拆解一下,了解现在控制器的硬件设计,硬件框架,器件造型等