自带触发和普通触发是示波器设计中比较重要的两个功能,本章节为大家讲解二代示波器中自动触发和普通触发的实现。
9.1 自动触发
9.2 普通触发
9.3 总结
9.1 自动触发
由于示波器模拟前端模块稍有些问题,所以自动触发功能是用软件实现的。软件实现自动触发比较容易实现,具体的实现代码如下:
/* 通过软件检测实现上升沿触发,并保留最后600的数据不做检测,用于直接显示 2048-600 = 1448; */
j = 0;
for(i = 0; i < 1448; i++)
{
j++;
if((g_DSO1->usWaveBufTemp[i] > g_TrigVol->usTrigValue) &&
(g_DSO1->usWaveBufTemp[i+1] < g_TrigVol->usTrigValue))
{
break;
}
}
g_DSO1->usWaveBufTemp是2048个ADC数据的缓冲区,g_TrigVol->usTrigValue是上升沿触发值。for循环的作用就是从1448个数据中找到满足触发值的位置,判断方法也比较简单,大于前一个值小于后一个值即可。
保留600个数据是因为这个大小是波形显示区一次可以显示的波形个数。如果从前2048-600 = 1448个数据中检索不到满足要求的数据将不再检索,直接显示末尾的600个数据,如果检测到将直接从for循环里面退出。
这个方法在实际测试中比较好用,另外上升沿阀值的判断还不够严谨,大家有兴趣可以继续完善下。
9.2 普通触发
普通触发的实现是基于ADC的模拟看门狗功能,通过设置不同看门狗阀值实现不同的触发电压。由于使能了看门狗中断,检测到外部触发电压后会进入ADC模拟看门狗中断。在中断里面判断是否是上升沿触发,如果是的话,会关闭模拟看门狗中断并开启一个定时器计数功能,目的是为了采集这个触发电压前后各1024个ADC数据,基本的实现思路就是这个样子的。
下面把实际的实现为大家做个说明:
第1步:将ADC3配置使能模拟看门狗功能。
/*ADC3的配置*****************************************************************/
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC3;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
/* ADC3 规则通道配置 */
ADC_Init(ADC3, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);
/* 使能 ADC3 DMA */
ADC_DMACmd(ADC3, ENABLE);
/* 配置模拟看门狗的阀值 注意别配置反了,要不一直进入中断 */
ADC_AnalogWatchdogThresholdsConfig(ADC3, 4095, 0);
/* 配置模拟看门狗监测ADC3的通道10 */
ADC_AnalogWatchdogSingleChannelConfig(ADC3, ADC_Channel_10);
/* 使能一个规则通道的看门狗 */
ADC_AnalogWatchdogCmd(ADC3, ADC_AnalogWatchdog_SingleRegEnable);
/* 使能模拟看门狗中断 */
ADC_ITConfig(ADC3, ADC_IT_AWD, ENABLE);
/* 使能DMA请求 -------------------------------------------------------------*/
ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);
/* Enable ADC3 --------------------------------------------------------------*/
ADC_Cmd(ADC3, ENABLE);
特别注意函数ADC_AnalogWatchdogThresholdsConfig的设置,因为是12位分辨率的ADC,最大值就是2^12 – 1 = 4095,这里设置为4095表示超过4095才会触发模拟看门狗中断,由于已经是最大值了,所以不会触发模拟看门狗中断。
第2步:模拟看门狗中断。
达到设置的模拟看门狗触发值会进入到这个中断里面。
/*
*********************************************************************************************************
* 函 数 名: ADC_IRQHandler
* 功能说明: 模拟看门狗中断服务程序。
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void ADC_IRQHandler()
{
/* 读取DMA剩余要传输的数目 */
g_usTrigCount = DMA2_Stream1->NDTR;
/* 确认是否是ADC3的看门狗中断 */
if((ADC3->SR)&0x01)
{
/* 取触发值的前一个点,查看是否是在阀值范围内,从而判断是上升沿还是下降沿 */
if(g_usTrigCount == 10240)
{
/* 剩余10240表示触发值是ADC3ConvertedValue[10239]是触发值,那么上一个点就是10238 */
g_usTrigTempFlag = ADC3ConvertedValue[10238];
}
else if(g_usTrigCount == 10239)
{
/* 剩余10239表示触发值是ADC3ConvertedValue[0]是触发值,那么上一个点就是10239 */
g_usTrigTempFlag = ADC3ConvertedValue[10239];
}
else
{
/* 剩余10239表示触发值是ADC3ConvertedValue[0]是触发值,那么上一个点就是10239 */
g_usTrigTempFlag = ADC3ConvertedValue[10238 - g_usTrigCount];
}
/* 判断是否是上升沿,是的话开启定时器记录ADC数据 */
if(g_usTrigTempFlag <= g_TrigVol->usTrigValue)
{
/* 关闭ADC3的看门狗中断 */
ADC3->CR1 &= 0xffffffbf;
TriggerFlag = 1;
/* 启动定时器计数 */
TIM8->CR1 |= 0x01;
}
/* 清除挂起标志 */
ADC3->SR &= 0xfe;
}
}
进入到这个中断后,主要做了一件事,判断是否是上升沿,如果是上升沿的话,将关闭模拟看门狗并开启定时器测量功能。也就是下面第3步要讲解的。
第3步:初始化一个定时器做时间测量,表示检测到触发值后记录一段时间的波形。
/*
*********************************************************************************************************
* 函 数 名: TIM8_MeasureTrigConfig
* 功能说明: 使用TIM8为普通触发模式下数据采集计时,定时采集触发值前后的1024个ADC数据
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
*/
/*
每次捕获采集触发值前后的1024个ADC数据(单通道)。
*/
const uint32_t g_TrigFreqTable[][2] =
{
{60, 1024}, //2.8Msps 168000000/2800000 = 60 => 60 * 1024
{84, 1024}, //2Msps 168000000/2000000 = 84 => 84 * 1024
{168, 1024}, //1Msps 168000000/1000000 = 168 => 168 * 1024
{336, 1024}, //500Ksps 168000000/500000 = 336 => 336 * 1024
{840, 1024}, //200Ksps 168000000/200000 = 840 => 840 * 1024
{1680, 1024}, //100Ksps 168000000/100000 = 1680 => 1680 * 1024
{3360, 1024}, //50Ksps 168000000/50000 = 3360 => 3360 * 1024
{8400, 1024}, //20Ksps 168000000/20000 = 8400 => 8400 * 1024
{16800, 1024}, //10Ksps 168000000/10000 = 16800 => 16800 * 1024
{33600, 1024}, //5Ksps 168000000/5000 = 33600 => 33600 * 1024
/* 下面5种采样频率下刷新较慢,因为采集前后1024个ADC的时间较长 */
{42000, 2048}, //2Ksps 168000000/2000 = 84000 => 84000 * 1024
{42000, 4096}, //1Ksps 168000000/1000 = 168000 => 168000 * 1024
{42000, 8192}, //500sps 168000000/500 = 336000 => 336000 * 1024
{42000, 20480}, //200sps 168000000/200 = 840000 => 840000 * 1024
{42000, 40960}, //100sps 168000000/100 = 1680000 => 1680000 * 1024
/* 下面这几种采样率不做触发支持 */
{42000, 40960}, //50sps
{42000, 40960}, //20sps
{42000, 40960}, //10sps
{42000, 40960}, //5sps
{42000, 40960}, //2sps
{42000, 40960}, //1sps
};
void TIM8_MeasureTrigConfig(void)
{
TIM_TimeBaseInitTypeDef TIM_BaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* 开启时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
/* 加上第一次进入中断的标志,进入中断后将其置1 */
g_usFirstTimeIRQFlag = 0;
/* 使能定时器8中断 */
NVIC_InitStructure.NVIC_IRQChannel = TIM8_UP_TIM13_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* 定时器配置 */
TimeBaseId = 1; /* 开机后按照ADC单通道1Msps进行配置 */
TIM_DeInit(TIM8);
TIM_BaseInitStructure.TIM_Period = g_TrigFreqTable[TimeBaseId][0] - 1;
TIM_BaseInitStructure.TIM_Prescaler = g_TrigFreqTable[TimeBaseId][1] - 1;
TIM_BaseInitStructure.TIM_ClockDivision = 0;
TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM8, &TIM_BaseInitStructure);
TIM_ITConfig(TIM8, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM8, DISABLE);
}
/*
*********************************************************************************************************
* 函 数 名: Time8Recorder
* 功能说明: 使用TIM8为普通触发模式下数据采集计时,定时采集触发值前后的1024个ADC数据
* 形 参:无
* 返 回 值: 无
*********************************************************************************************************
上一篇:示波器设计—双通道ADC驱动
下一篇:示波器设计—测量功能
推荐阅读最新更新时间:2024-11-06 22:46
- CAT4201、CrM 降压 LED 驱动器评估板
- 西南石油南充_PCB
- SI5342-D-EVB,基于 Si5342 任意频率、任意输出、抖动衰减时钟乘法器的评估板,修订版 D
- DC489A-A,使用 LTC5507ES6 低频至高频射频功率检测器的演示板
- 使用 ROHM Semiconductor 的 BD48K24G-TL 的参考设计
- 医疗主控
- 将 ADL5371 I/Q 调制器连接到 AD9779A 双通道、1 GSPS 高速 DAC
- STPA002CD-48X 的典型应用电路 (Flexiwatt27),4 x 52 W 四桥功率放大器,低电压运行
- DC9022A,SmartMesh WirelessHART 射频认证入门套件 + DC9018A-C
- INA226模块
- Nexperia有奖直播|电动汽车中车规功率MOSFET和氮化镓器件的介绍及应用
- 最热8月,带着你的原创一起High!
- 有奖问答|ADI应用之旅——电池管理及智慧储能篇
- 平头哥RVB2601开源应用方案征集来啊~100套板卡助阵,天猫精灵智能套装礼品组等你抱走~
- EEWorld邀你来拆解(第7期)——拆拆减肥利器,看看跳绳里都有什么
- 安森美半导体重磅推出超低功耗蓝牙芯片 RSL10 — 观视频答题送样片 更有丰富礼品等你拿!
- 下载有礼|是德科技:测试设备如何影响产品质量调研报告
- 有奖大调查:你遇到的电源设计挑战有哪些?
- 有奖报名|TI MSPM0 在【电力输送和工厂自动化与控制系统】、【家用电器和电机控制】中的典型应用