STM32 ADC规则组和注入组配置方法

//############################################################
//近期在用STM32F103编写无刷电机矢量控制,在配置ADC模式时遇到很多奇怪的问题,网上能说清楚的资料太少,
//公布我配置的结果,实测OK
//3组规则通道连续转换+DMA
//2组注入通道TIM1的4通道触发(规格书未说明是上升沿还是下降沿触发,实测波形为上升沿触发)
//############################################################
#include "ADC_int.h"
#include "GPIO_int.h"
#include "Task_function.h"
#include "Tim1_PWM.h"

#define ADC1_DR_Address 0x4001244C

extern logic logicContr;
extern ADCSamp ADCSampPare;
uint16_t ADC_ConvertedValue[3]={0};
uint16_t BUS_CurrProtection=600; //通过母线电流值保护硬件 软件处理 3A左右为600峰值
extern uint8_t flag_injectedoffset;
extern uint8_t flag_regularoffset;

uint8_t injectedoffsecount = 0;
uint8_t regularoffsecount = 0;

void ADC1_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

/* ADC1 Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* ADC1 DeInit */
ADC_DeInit(ADC1);

/* Initialize ADC structure */
ADC_StructInit(&ADC_InitStructure);

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //连续转换开启
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 3; //设置转换序列长度为2
ADC_Init(ADC1, &ADC_InitStructure);

RCC_ADCCLKConfig( RCC_PCLK2_Div2 ); // 72/2

ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 1, ADC_SampleTime_13Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 2, ADC_SampleTime_13Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_13,3, ADC_SampleTime_13Cycles5);

ADC_InjectedSequencerLengthConfig(ADC1, 2);
ADC_InjectedChannelConfig(ADC1, ADC_Channel_3, 1,ADC_SampleTime_13Cycles5);
ADC_InjectedChannelConfig(ADC1, ADC_Channel_6, 2,ADC_SampleTime_13Cycles5);
ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_T1_CC4);
ADC_ExternalTrigInjectedConvCmd(ADC1, ENABLE); //使能或者失能 ADCx 的经外部触发启动注入组转换功能
ADC_ITConfig(ADC1,ADC_IT_JEOC,ENABLE); //ENABLE INJECTED INTERRUPT

ADC_AutoInjectedConvCmd(ADC1, DISABLE); //使能或者失能指定 ADC 在规则组转化后自动开始注入组转换
ADC_ExternalTrigConvCmd(ADC1, DISABLE); //软件启动注入组转换

// Enable ADC1
ADC_Cmd(ADC1, ENABLE);
// 开启ADC的DMA支持(要实现DMA功能,还需独立配置DMA通道等参数)
ADC_DMACmd(ADC1, ENABLE);

// 下面是ADC自动校准,开机后需执行一次,保证精度
// Enable ADC1 reset calibaration register
ADC_ResetCalibration(ADC1);
// Check the end of ADC1 reset calibration register
while(ADC_GetResetCalibrationStatus(ADC1));

// Start ADC1 calibaration
ADC_StartCalibration(ADC1);
// Check the end of ADC1 calibration
while(ADC_GetCalibrationStatus(ADC1));
// ADC自动校准结束---------------
//启动第一次AD转换
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
//因为已经配置好了DMA,接下来AD自动连续转换,结果自动保存在RegularConvData_Tab处

NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//指定抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//指定响应优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
// NVIC_InitTypeDef NVIC_InitStructure;

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);

DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_ConvertedValue;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
//BufferSize=2,因为ADC转换序列有2个通道
//如此设置,使序列1结果放在RegularConvData_Tab[0],序列2结果放在RegularConvData_Tab[1]
DMA_InitStructure.DMA_BufferSize = 3;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
//循环模式开启,Buffer写满后,自动回到初始地址开始传输
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
//配置完成后,启动DMA通道
DMA_Cmd(DMA1_Channel1, ENABLE);

// DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE); //配置DMA发送完成后产生中断
// //配置TIM1的更新中断使能
// NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//指定抢占优先级1
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//指定响应优先级0
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
//
}

void ADC_InjectedOffset( void )
{
static uint32_t sum_U = 0;
static uint32_t sum_V = 0;

if( injectedoffsecount < 128 )
{
sum_U += ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1);
sum_V += ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_2);
injectedoffsecount++;
}
else
{
ADCSampPare.OffsetPhaseU_Curr = sum_U / 128;
ADCSampPare.OffsetPhaseV_Curr = sum_V / 128;
flag_injectedoffset = 1;
injectedoffsecount = 0;
sum_U = 0;
sum_V = 0;
}
}

void ADC_InjectedSample( void )
{
ADCSampPare.PhaseU_Curr = ( ( ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1) - ADCSampPare.OffsetPhaseU_Curr ) << 1 );
ADCSampPare.PhaseV_Curr = ( ( ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_2) - ADCSampPare.OffsetPhaseV_Curr ) << 1 ); // Q12格式左移1位,放大5倍,采样电阻0.05R = 1/5/0.05 = 4,左移2位
}

//校准作用,电流传感器的偏移值为1.65V
void ADC_RegularOffset(void) // 没有PWM输出是调用
{
static uint32_t sum_BUS = 0;

if( regularoffsecount < 128 )
{
sum_BUS += ADC_ConvertedValue[0];
regularoffsecount++;
}
else
{

ADCSampPare.OffsetBUS_Curr = sum_BUS / 128;
flag_regularoffset = 1;
regularoffsecount = 0;
sum_BUS = 0;
}
}

void ADC_RegularSample( void ) // 放在PWM中断进来后,采样时间为1us左右,(7cycles) 保证在PWM中断后进来采样后为在PWM中间采集相电流
{
// 把电流采集运算偏执后,左移1为,乘2倍后将电流传感器AD采集值转换IQ12格式 -4096到4096
// 此电流乘2倍与硬件差分放大电流2K/1K电阻放大2倍没有关系
// 此传感器量程,100毫欧 运算放大器2倍,硬件0到3.3等效-1.6到1.6,100mr电阻传感器量程大约±8A
// 若硬件修改,按照此算法比例计算
ADCSampPare.BUS_Curr = ( ( -ADC_ConvertedValue[0] + ADCSampPare.OffsetBUS_Curr ) << 1 ) + 25; // 补偿一阶低通滤波后的小的插值25经验值
ADCSampPare.RP_speed_Voltage = ADC_ConvertedValue[1];

if( ADCSampPare.RP_speed_Voltage > 2048 )
{
ADCSampPare.RP_speed_Voltage -= 2048;
}
else
{
ADCSampPare.RP_speed_Voltage = 0;
}
ADCSampPare.RP_speed_Voltage = ADCSampPare.RP_speed_Voltage << 1;

ADCSampPare.BUS_Voltage = ADC_ConvertedValue[2];
// 一阶低通数字滤波器 公式查文献百度 历史量0.96 采集新值0.04
ADCSampPare.BUS_CurrF = _IQ10mpy( ADCSampPare.Coeff_filterK1, ADCSampPare.BUS_CurrF ) + _IQ10mpy( ADCSampPare.Coeff_filterK2, ADCSampPare.BUS_Curr );

}

void Protection_software(void) //通过母线电流值保护硬件 软件处理 3A左右为600
{
if( Abs( ADCSampPare.BUS_CurrF ) > BUS_CurrProtection ) // 大约为3A
{
Stop_Motor(); // 关闭电机停止
logicContr.Start_order=0;
}
}

原文地址:https://www.cnblogs.com/hushunlin/p/12334286.html

时间: 2024-10-04 00:26:59

STM32 ADC规则组和注入组配置方法的相关文章

Windows 组策略加固攻击及配置方法

1.  直接执行 1.1.   IE地址栏执行 1.1.1.攻击步骤 c:\windows\system32\cmd.exe dsquery groups 增加账号  net user test111 "Ab123456" /add 查看当前用户 net user 增加用户为administrators组 net localgroup administrators test111 /add 查看当前用户权限 net user test111 删掉该用户netuser test111 /

MySQL组复制(4):配置多主模型的组复制

在这一篇,我演示的是如何配置MySQL组复制的多主模型(multi-primary).在配置上,多主模型的组复制和单主模型基本没区别. 本文仅为搭建和维护多主模型组复制抛块小砖,若对其间涉及的术语和理论有所疑惑,可参看: 单主模型相关内容的大长文:配置单主模型的组复制. 组复制的理论:MySQL组复制官方手册翻译. 使用组复制技术,必须要了解它的要求和局限性.见:组复制的要求和局限性. 1.组复制:单主和多主模型 MySQL组复制支持单主模型和多主模型,它们都能保证MySQL数据库的高可用. 单

简述centOS 7系统用户和组的管理及配置

一.1.Linux中用户的类型超级管理员root,默认ID为0:超级管理员root默认ID0只能有一个普通用户除管理员以外用户创建的账户都是普通用户:默认ID500~60000程序用户管理Linux系统的应用程序使用:默认ID1~4992.组的类型基本组和附加组:组是用户的集合3.用户关联配置文件的类型4.添加账户useradd常见的选项-d指定用户宿主目录,默认在/home中-e指定账户失效的时间-g指定基本组的组号或者名字-G指定附加组的组号或者名字-m不建立宿主目录-s指定登录shell5

STM32——ADC

STM32--ADC 宗旨:技术的学习是有限的,分享的精神的无限的. 一.ADC指标 有 18 个通道,可测量 16 个外部和 2 个内部信号源.各通道的 A/D 转换可以单次.连续.扫描或间断模式执行 :ADC的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中 :模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高 / 低阈值. 对于 ADC 来说,我们最关注的就是它的分辨率.转换时间.ADC 类型.参考电压范围: (1)分辨率:12 位分辨率.不能直接测量负电压,所以没有符号位,

STM32 ADC 测电压

1. STM32F103 ADC 本例使用STM32F103芯片的PA1引脚测试模拟输入的电压值. 查看文档<STM32F103X.pdf>第31页,引脚定义图: 得知PA1使用ADC1的通道1. 查看文档<STM32F103X.pdf>第13页,时钟树图: 得知ADC1可2,4,6,8分频,又ADC输入时钟不得超过14MHZ(参见STM32参考手册RM0008第11章ADC). //初始化ADC //这里我们仅以规则通道为例 //我们默认将开启通道0~3 void Adc_Ini

WSFC2016 VM顺序组与管理组

在我们管理虚拟化场景或群集应用场景时,可能经常会经常碰见一个需求,即依赖性顺序,开发人员可能会需要保证一系列联合工作虚拟机或群集应用的启动顺序,确保最底层需要的资源启动后,再按照顺序陆续启动其它资源. 针对于依赖性启动的需求,如果是在没有群集的单机Hyper-V场景下,我们可以通过设置虚拟机的自动启动属性来解决此问题,例如,一套sharepoint环境,有DC,DB,AP,WEB,我们可以依次设置各虚拟机自动启动的延迟时间,0,30,50,80.这样做了之后,在单机情况下,当宿主机重新启动,可以

全局组,通用组,本地组

首先我们需要明确一点:为什么我们需要建立组? 答案很简单:为了管理方便! 其实计算机文件或者文件夹的控制权限是在属性的安全的选项卡中设定的,如下图所示: 在"组或用户名称"中可以添加对此文件夹行使权限的用户或者组. 现在来看这样一种情况: 你是一个域的管理员,在文件服务器上建立了一个共享文件夹,用来放置一些财务部专用文档,假如你有两个选择: 1.在安全属性页中一个一个添加财务部的人员并配置相应的权限. 2.在域控制器中创建财务部的组(包含所有财务部人员),在安全属性页中添加财务部组 假

阿里云ipv6安全组匹配所有ip的方法

IPv4和IPv6通信彼此独立.您需要为ECS实例单独配置IPv6安全组规则. 操作步骤 登录ECS控制台. 在左侧导航栏,单击网络和安全 > 安全组. 找到目标安全组,然后单击配置规则. 单击添加安全组规则. 配置安全组规则,授权类型选择IPv6地址段访问,然后输入授权的IPv6地址段.如果输入::/0则代表所有IPv6地址. 安全组详细的配置说明,请参考创建安全组. 原文地址:https://www.cnblogs.com/kangleweb/p/11445292.html

Oracle在线调整redo日志组数及组成员

Oracle在线调整redo日志组数及组成员 一.调整redo日志组大小 操作原因: redo日志一般设置让日志转换时间为10-20分钟,转换太频繁会影响性能.通常情况下每小时不要超过6次!如果AWR(Automated Workload Repository 自动负载信息库) report中log file switch checkpoint incomplete) 比较大,说明redo log之间的切换过于频繁.可以通过增加redo log size来降低切换的频率.但如果redo log