STM32 HAL库F103系列之ADC实验(二)

ops/2024/10/25 8:21:00/

多通道ADC采集(DMA读取)实验

这个实验与单通道ADC(DMA读取)实验大致相同

实验简要:

1,功能描述   通过DMA读取数据

        通过ADC1通道0/1/2/3/4/5PA0/1/2/3/4/5)采集测试电压,并显示ADC转换的数字量及换算后的电压值

2,确定最小刻度

        VREF+ = 3.3V  0VVIN3.3V  最小刻度 = 3.3 / 4096          F4/F7/H7系列还需要考虑ADC分辨率

3,确定转换时间

        采样时间239.5ADC时钟周期为例,可以得到转换时间为21us

4,模式组合

        连续转换模式、使用扫描模式

源码

adc.c

#include "./BSP/ADC/adc.h"DMA_HandleTypeDef g_dma_nch_adc_handle;
ADC_HandleTypeDef g_adc_nch_dma_handle;
uint8_t g_adc_dma_sta;/* ADC N通道(6通道) DMA读取 初始化函数 */
void adc_nch_dma_init(uint32_t mar)
{ADC_ChannelConfTypeDef adc_ch_conf;__HAL_RCC_DMA1_CLK_ENABLE();g_dma_nch_adc_handle.Instance = DMA1_Channel1;g_dma_nch_adc_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;g_dma_nch_adc_handle.Init.PeriphInc = DMA_PINC_DISABLE;g_dma_nch_adc_handle.Init.MemInc = DMA_MINC_ENABLE;g_dma_nch_adc_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;g_dma_nch_adc_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;g_dma_nch_adc_handle.Init.Mode = DMA_NORMAL;g_dma_nch_adc_handle.Init.Priority = DMA_PRIORITY_MEDIUM;HAL_DMA_Init(&g_dma_nch_adc_handle);__HAL_LINKDMA(&g_adc_nch_dma_handle, DMA_Handle, g_dma_nch_adc_handle);g_adc_nch_dma_handle.Instance = ADC1;g_adc_nch_dma_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;g_adc_nch_dma_handle.Init.ScanConvMode = ADC_SCAN_ENABLE;g_adc_nch_dma_handle.Init.ContinuousConvMode = ENABLE;g_adc_nch_dma_handle.Init.NbrOfConversion = 6;g_adc_nch_dma_handle.Init.DiscontinuousConvMode = DISABLE;g_adc_nch_dma_handle.Init.NbrOfDiscConversion = 0;g_adc_nch_dma_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;HAL_ADC_Init(&g_adc_nch_dma_handle);HAL_ADCEx_Calibration_Start(&g_adc_nch_dma_handle);adc_ch_conf.Channel = ADC_CHANNEL_0;adc_ch_conf.Rank = ADC_REGULAR_RANK_1;adc_ch_conf.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);adc_ch_conf.Channel = ADC_CHANNEL_1;adc_ch_conf.Rank = ADC_REGULAR_RANK_2;HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);adc_ch_conf.Channel = ADC_CHANNEL_2;adc_ch_conf.Rank = ADC_REGULAR_RANK_3;HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);adc_ch_conf.Channel = ADC_CHANNEL_3;adc_ch_conf.Rank = ADC_REGULAR_RANK_4;HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);adc_ch_conf.Channel = ADC_CHANNEL_4;adc_ch_conf.Rank = ADC_REGULAR_RANK_5;HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);adc_ch_conf.Channel = ADC_CHANNEL_5;adc_ch_conf.Rank = ADC_REGULAR_RANK_6;HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 3, 3);HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);HAL_DMA_Start_IT(&g_dma_nch_adc_handle, (uint32_t)&ADC1->DR, mar, 0);HAL_ADC_Start_DMA(&g_adc_nch_dma_handle, &mar ,0);
}/* ADC MSP初始化函数 */
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{if(hadc->Instance == ADC1){GPIO_InitTypeDef gpio_init_struct;RCC_PeriphCLKInitTypeDef adc_clk_init = {0};__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_ADC1_CLK_ENABLE();gpio_init_struct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;gpio_init_struct.Mode = GPIO_MODE_ANALOG;HAL_GPIO_Init(GPIOA, &gpio_init_struct); adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);}
}/* 使能一次ADC DMA传输函数 */
void adc_dma_enable(uint16_t cndtr)
{ADC1->CR2 &= ~(1 << 0);DMA1_Channel1->CCR &= ~(1 << 0);while (DMA1_Channel1->CCR & (1 << 0));DMA1_Channel1->CNDTR = cndtr;DMA1_Channel1->CCR |= 1 << 0;ADC1->CR2 |= 1 << 0;ADC1->CR2 |= 1 << 22;
}/* ADC DMA采集中断服务函数 */
void DMA1_Channel1_IRQHandler(void)
{if (DMA1->ISR & (1<<1)){g_adc_dma_sta = 1;DMA1->IFCR |= 1 << 1;}
}

adc.h

#ifndef __ADC_H
#define __ADC_H#include "./SYSTEM/sys/sys.h"void adc_nch_dma_init(uint32_t mar);
void adc_dma_enable(uint16_t cndtr);#endif

main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/ADC/adc.h"#define ADC_DMA_BUF_SIZE        50 * 6      /* ADC DMA采集 BUF大小, 应等于ADC通道数的整数倍 */
uint16_t g_adc_dma_buf[ADC_DMA_BUF_SIZE];   /* ADC DMA BUF */extern uint8_t g_adc_dma_sta;               /* DMA传输状态标志, 0,未完成; 1, 已完成 */int main(void)
{uint16_t i,j;uint16_t adcx;uint32_t sum;float temp;HAL_Init();                                 /* 初始化HAL库 */sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟, 72Mhz */delay_init(72);                             /* 延时初始化 */usart_init(115200);                         /* 串口初始化为115200 */led_init();                                 /* 初始化LED */lcd_init();                                 /* 初始化LCD */adc_nch_dma_init((uint32_t)&g_adc_dma_buf); /* 初始化ADC DMA采集 */lcd_show_string(30,  50, 200, 16, 16, "STM32", RED);lcd_show_string(30,  70, 200, 16, 16, "ADC 6CH DMA TEST", RED);lcd_show_string(30,  90, 200, 16, 16, "ATOM@ALIENTEK", RED);lcd_show_string(30, 110, 200, 12, 12, "ADC1_CH0_VAL:", BLUE);lcd_show_string(30, 122, 200, 12, 12, "ADC1_CH0_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */lcd_show_string(30, 140, 200, 12, 12, "ADC1_CH1_VAL:", BLUE);lcd_show_string(30, 152, 200, 12, 12, "ADC1_CH1_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */lcd_show_string(30, 170, 200, 12, 12, "ADC1_CH2_VAL:", BLUE);lcd_show_string(30, 182, 200, 12, 12, "ADC1_CH2_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */lcd_show_string(30, 200, 200, 12, 12, "ADC1_CH3_VAL:", BLUE);lcd_show_string(30, 212, 200, 12, 12, "ADC1_CH3_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */lcd_show_string(30, 230, 200, 12, 12, "ADC1_CH4_VAL:", BLUE);lcd_show_string(30, 242, 200, 12, 12, "ADC1_CH4_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */lcd_show_string(30, 260, 200, 12, 12, "ADC1_CH5_VAL:", BLUE);lcd_show_string(30, 272, 200, 12, 12, "ADC1_CH5_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */adc_dma_enable(ADC_DMA_BUF_SIZE);   /* 启动ADC DMA采集 */while (1){if (g_adc_dma_sta == 1){/* 循环显示通道0~通道5的结果 */for(j = 0; j < 6; j++)  /* 遍历6个通道 */{sum = 0; /* 清零 */for (i = 0; i < ADC_DMA_BUF_SIZE / 6; i++)  /* 每个通道采集了50次数据,进行50次累加 */{sum += g_adc_dma_buf[(6 * i) + j];      /* 相同通道的转换数据累加 */}adcx = sum / (ADC_DMA_BUF_SIZE / 6);        /* 取平均值 *//* 显示结果 */lcd_show_xnum(108, 110 + (j * 30), adcx, 4, 12, 0, BLUE);   /* 显示ADC采样后的原始值 */temp = (float)adcx * (3.3 / 4096);  /* 获取计算后的带小数的实际电压值,比如3.1111 */adcx = temp;                        /* 赋值整数部分给adcx变量,因为adcx为u16整形 */lcd_show_xnum(108, 122 + (j * 30), adcx, 1, 12, 0, BLUE);   /* 显示电压值的整数部分,3.1111的话,这里就是显示3 */temp -= adcx;                       /* 把已经显示的整数部分去掉,留下小数部分,比如3.1111-3=0.1111 */temp *= 1000;                       /* 小数部分乘以1000,例如:0.1111就转换为111.1,相当于保留三位小数。 */lcd_show_xnum(120, 122 + (j * 30), temp, 3, 12, 0X80, BLUE);/* 显示小数部分(前面转换为了整形显示),这里显示的就是111. */}g_adc_dma_sta = 0;                      /* 清除DMA采集完成状态标志 */adc_dma_enable(ADC_DMA_BUF_SIZE);       /* 启动下一次ADC DMA采集 */}LED0_TOGGLE();delay_ms(100);}
}

单通道ADC过采样实验

这个实验与单通道ADC(DMA读取)实验大致相同

如何用过采样和求平均值的方式提高ADC的分辨率?

1)如何确定过采样率

        根据要增加的分辨率位数计算过采样频率方程:

                     

2)如何求均值

        举个例子:12位分辨率的ADC提高4位分辨率,采样频率就要提高256

        即需要256次采集才能得到一次16位分辨率的数据

        然后将这256次采集结果求和,求和的结果再右移4位,就得到提高分辨率后的结果

        注意:提高N 位分辨率,需要 右移N

实验简要:

1,功能描述        通过DMA读取数据

        通过ADC1通道1PA1)过采样实现16位分辨率采集电压,并显示ADC转换的数字量及换算后的电压值

2,确定最小刻度

        VREF+ = 3.3V  0VVIN3.3V  最小刻度 = 3.3 / 4096          F4/F7/H7系列还需要考虑ADC分辨率

3,确定转换时间

        采样时间设置为最小值1.5ADC时钟周期,可以得到转换时间为1.17us * 256

4,模式组合

        连续转换模式、不使用扫描模式

源码

adc.c

#include "./BSP/ADC/adc.h"DMA_HandleTypeDef g_dma_adc_handle;
ADC_HandleTypeDef g_adc_dma_handle;
uint8_t g_adc_dma_sta;/* ADC DMA读取 初始化函数 */
void adc_dma_init(uint32_t mar)
{ADC_ChannelConfTypeDef adc_ch_conf;__HAL_RCC_DMA1_CLK_ENABLE();g_dma_adc_handle.Instance = DMA1_Channel1;g_dma_adc_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;g_dma_adc_handle.Init.PeriphInc = DMA_PINC_DISABLE;g_dma_adc_handle.Init.MemInc = DMA_MINC_ENABLE;g_dma_adc_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;g_dma_adc_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;g_dma_adc_handle.Init.Mode = DMA_NORMAL;g_dma_adc_handle.Init.Priority = DMA_PRIORITY_MEDIUM;HAL_DMA_Init(&g_dma_adc_handle);__HAL_LINKDMA(&g_adc_dma_handle, DMA_Handle, g_dma_adc_handle);g_adc_dma_handle.Instance = ADC1;g_adc_dma_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;g_adc_dma_handle.Init.ScanConvMode = ADC_SCAN_DISABLE;g_adc_dma_handle.Init.ContinuousConvMode = ENABLE;g_adc_dma_handle.Init.NbrOfConversion = 1;g_adc_dma_handle.Init.DiscontinuousConvMode = DISABLE;g_adc_dma_handle.Init.NbrOfDiscConversion = 0;g_adc_dma_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;HAL_ADC_Init(&g_adc_dma_handle);HAL_ADCEx_Calibration_Start(&g_adc_dma_handle);adc_ch_conf.Channel = ADC_CHANNEL_1;adc_ch_conf.Rank = ADC_REGULAR_RANK_1;adc_ch_conf.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;HAL_ADC_ConfigChannel(&g_adc_dma_handle, &adc_ch_conf);HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 3, 3);HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);HAL_DMA_Start_IT(&g_dma_adc_handle, (uint32_t)&ADC1->DR, mar, 0);HAL_ADC_Start_DMA(&g_adc_dma_handle, &mar ,0);
}/* ADC MSP初始化函数 */
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{if(hadc->Instance == ADC1){GPIO_InitTypeDef gpio_init_struct;RCC_PeriphCLKInitTypeDef adc_clk_init = {0};__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_ADC1_CLK_ENABLE();gpio_init_struct.Pin = GPIO_PIN_1;gpio_init_struct.Mode = GPIO_MODE_ANALOG;HAL_GPIO_Init(GPIOA, &gpio_init_struct); adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);}
}/* 使能一次ADC DMA传输函数 */
void adc_dma_enable(uint16_t cndtr)
{ADC1->CR2 &= ~(1 << 0);DMA1_Channel1->CCR &= ~(1 << 0);while (DMA1_Channel1->CCR & (1 << 0));DMA1_Channel1->CNDTR = cndtr;DMA1_Channel1->CCR |= 1 << 0;ADC1->CR2 |= 1 << 0;ADC1->CR2 |= 1 << 22;//    __HAL_ADC_DISABLE(&g_adc_dma_handle);
//    
//    __HAL_DMA_DISABLE(&g_dma_adc_handle);
//    while (__HAL_DMA_GET_FLAG(&g_dma_adc_handle, __HAL_DMA_GET_TC_FLAG_INDEX(&g_dma_adc_handle)));
//    DMA1_Channel1->CNDTR = cndtr;
//    __HAL_DMA_ENABLE(&g_dma_adc_handle);
//    
//    __HAL_ADC_ENABLE(&g_adc_dma_handle);
//    HAL_ADC_Start(&g_adc_dma_handle);
}/* ADC DMA采集中断服务函数 */
void DMA1_Channel1_IRQHandler(void)
{if (DMA1->ISR & (1<<1)){g_adc_dma_sta = 1;DMA1->IFCR |= 1 << 1;}
}

adc.h

#ifndef __ADC_H
#define __ADC_H#include "./SYSTEM/sys/sys.h"void adc_dma_init(uint32_t mar);
void adc_dma_enable(uint16_t cndtr);#endif

main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/ADC/adc.h"/* ADC过采样技术, 是利用ADC多次采集的方式, 来提高ADC精度, 采样速度每提高4倍* 采样精度提高 1bit, 同时, ADC采样速度降低4倍, 如提高4bit精度, 需要256次采集* 才能得出1次数据, 相当于ADC速度慢了256倍. 理论上只要ADC足够快, 我们可以无限* 提高ADC精度, 但实际上ADC并不是无限快的, 而且由于ADC性能限制, 并不是位数无限* 提高结果就越好, 需要根据自己的实际需求和ADC的实际性能来权衡.*/
#define ADC_OVERSAMPLE_TIMES    256                         /* ADC过采样次数, 这里提高4bit分辨率, 需要256倍采样 */
#define ADC_DMA_BUF_SIZE        ADC_OVERSAMPLE_TIMES * 10   /* ADC DMA采集 BUF大小, 应等于过采样次数的整数倍 */uint16_t g_adc_dma_buf[ADC_DMA_BUF_SIZE];                   /* ADC DMA BUF */extern uint8_t g_adc_dma_sta;                               /* DMA传输状态标志, 0,未完成; 1, 已完成 */int main(void)
{uint16_t i;uint32_t adcx;uint32_t sum;float temp;HAL_Init();                                 /* 初始化HAL库 */sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟, 72Mhz */delay_init(72);                             /* 延时初始化 */usart_init(115200);                         /* 串口初始化为115200 */led_init();                                 /* 初始化LED */lcd_init();                                 /* 初始化LCD */adc_dma_init((uint32_t)&g_adc_dma_buf);     /* 初始化ADC DMA采集 */lcd_show_string(30,  50, 200, 16, 16, "STM32", RED);lcd_show_string(30,  70, 200, 16, 16, "ADC OverSample TEST", RED);lcd_show_string(30,  90, 200, 16, 16, "ATOM@ALIENTEK", RED);lcd_show_string(30, 110, 200, 16, 16, "ADC1_CH1_VAL:", BLUE);lcd_show_string(30, 130, 200, 16, 16, "ADC1_CH1_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */adc_dma_enable(ADC_DMA_BUF_SIZE);           /* 启动ADC DMA采集 */while (1){if (g_adc_dma_sta == 1){/* 计算DMA 采集到的ADC数据的平均值 */sum = 0;for (i = 0; i < ADC_DMA_BUF_SIZE; i++)   /* 累加 */{sum += g_adc_dma_buf[i];}adcx = sum / (ADC_DMA_BUF_SIZE / ADC_OVERSAMPLE_TIMES); /* 取平均值 */adcx >>= 4;   /* 除以2^4倍, 得到12+4位 ADC精度值, 注意: 提高 N bit精度, 需要 >> N *//* 显示结果 */lcd_show_xnum(134, 110, adcx, 5, 16, 0, BLUE);      /* 显示ADC采样后的原始值 */temp = (float)adcx * (3.3 / 65536);                 /* 获取计算后的带小数的实际电压值,比如3.1111 */adcx = temp;                                        /* 赋值整数部分给adcx变量,因为adcx为u16整形 */lcd_show_xnum(134, 130, adcx, 1, 16, 0, BLUE);      /* 显示电压值的整数部分,3.1111的话,这里就是显示3 */temp -= adcx;                                       /* 把已经显示的整数部分去掉,留下小数部分,比如3.1111-3=0.1111 */temp *= 1000;                                       /* 小数部分乘以1000,例如:0.1111就转换为111.1,相当于保留三位小数。 */lcd_show_xnum(150, 130, temp, 3, 16, 0X80, BLUE);   /* 显示小数部分(前面转换为了整形显示),这里显示的就是111. */g_adc_dma_sta = 0;                                  /* 清除DMA采集完成状态标志 */adc_dma_enable(ADC_DMA_BUF_SIZE);                   /* 启动下一次ADC DMA采集 */}LED0_TOGGLE();delay_ms(100);}
}


http://www.ppmy.cn/ops/8383.html

相关文章

python 判断变量是数字型还是字符型

python如何判断数据类型&#xff1f;方法如下&#xff1a; 使用type()函数&#xff1a; import types type(x) is types.IntType # 判断是否int 类型 type(x) is types.StringType #是否string类型可以不用记住types.StringType&#xff0c;即&#xff1a; import types type(…

MySQL基础篇总结

参考&#xff1a;黑马程序员MySQL基础视频链接 数据库基本操作 启动与停止 1.第一种方式&#xff1a; 1>以管理员身份运行cmd 2>在命令行窗口中输入: 启动:net start mysql80停止:net stop mysql80 2.第二种方式: 1>WinR快捷方式打开如下&#xff1a; 输入&#…

C++修炼之路之list--C++中的双向循环链表

目录 前言 一&#xff1a;正式之前先回顾数据结构中的双向循环链表 二&#xff1a;list的简介 三&#xff1a;STL中list常用接口函数的介绍及使用 1.构造函数接口 2.list迭代器 范围for 3.数据的修改接口函数 4.list容量操作函数 5.list的迭代器失效 6.演示代码和测…

Stable Diffusion UI 从安装到实现文字图片融合(光影字,错觉图)图片制作详细教程

前言 最近在实践大模型本地部署&#xff0c;前几天在本地部署了一个ChatGLM大模型&#xff0c;刚好环境搭好了&#xff0c;也支持跑Stable Diffusion&#xff0c;所以就安装了再尝试一下。 原因是之前在B站上有大佬做了一个Windows电脑能一键运行的Stable Diffusion的安装包&…

【机器学习】小波变换在特征提取中的实践与应用

小波变换在特征提取中的实践与应用 一、小波变换的基本原理与数学表达二、基于小波变换的特征提取方法与实例三、小波变换在特征提取中的优势与展望 在信号处理与数据分析领域&#xff0c;小波变换作为一种强大的数学工具&#xff0c;其多尺度分析特性使得它在特征提取中扮演着…

排序算法之堆排序

目录 一、简介二、代码实现三、应用场景 一、简介 算法平均时间复杂度最好时间复杂度最坏时间复杂度空间复杂度排序方式稳定性堆排序O( N N N log ⁡ 2 N \log_{2}N log2​N))O( N N N log ⁡ 2 N \log_{2}N log2​N))O( N N N log ⁡ 2 N \log_{2}N log2​N))O(1)In-place不稳…

Qt-控件篇

QPushbutton 1、设置按钮文本 pushButton->setText("按钮"); 2、获取按钮文本 pushButton->text(); 3、设置按钮的大小为特定值&#xff08;宽度和高度&#xff09; pushButton->setFixedSize(width,height); 4、设置按钮悬停时的工具提示文本。 pushButto…

SpringMvc的核心组件和执行流程

一、 springmvc的核心组件及作用 1.DispatcherServlet:前置控制器&#xff0c;是整个流程控制的核心&#xff0c;用来控制其他组件的执行&#xff0c;降低了其他组件的耦合性 2.Handler:控制器&#xff0c;完成具体的业务逻辑&#xff0c;当DispatcherServlet接收到请求后&am…