久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费
標題:
adc_dma進行采集時打印數據為0,不開dma數據能夠正常顯示,想問一下是什么原因
[打印本頁]
作者:
tfsrse
時間:
2024-10-21 16:10
標題:
adc_dma進行采集時打印數據為0,不開dma數據能夠正常顯示,想問一下是什么原因
51hei截圖20241021161025.png
(17.37 KB, 下載次數: 5)
下載附件
2024-10-21 16:10 上傳
/**
****************************************************************************************************
* @file adc.c
* @author 正點原子團隊(ALIENTEK)
* @version V1.3
* @date 2020-04-24
* @brief ADC 驅動代碼
* @license Copyright (c) 2020-2032, 廣州市星翼電子科技有限公司
****************************************************************************************************
* @attention
*
* 修改說明
* V1.0 20200423
* 第一次發布
* V1.1 20200423
* 1,支持ADC單通道DMA采集
* 2,新增adc_dma_init和adc_dma_enable函數.
* V1.2 20200423
* 1,支持ADC多通道DMA采集
* 2,新增adc_nch_dma_init函數.
* V1.3 20200424
* 1,支持內部溫度傳感器溫度采集
* 2,新增adc_temperature_init和adc_get_temperature函數.
*
****************************************************************************************************
*/
#include "./BSP/ADC/adc.h"
//#include "./BSP/DMA/dma.h"
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/usart/usart.h"
ADC_HandleTypeDef g_adc_handle; /* ADC句柄 */
DMA_HandleTypeDef g_dma_adc_handle; /* 與ADC關聯的DMA句柄 */
uint8_t g_adc_dma_sta = 0; /* DMA傳輸狀態標志, 0,未完成; 1, 已完成 */
uint16_t g_adc_value[ADC_CH_NUM * ADC_COLL] = {0}; /* 存儲ADC原始值 */
//float g_adc_u_value[ADC_CH_NUM] = {0}; /* 存儲ADC轉換后的電壓值 */
/********************************************************************/
/**
* @brief ADC初始化函數
* @note 本函數支持ADC1/ADC2任意通道, 但是不支持ADC3
* 我們使用12位精度, ADC采樣時鐘=12M, 轉換時間為: 采樣周期 + 12.5個ADC周期
* 設置最大采樣周期: 239.5, 則轉換時間 = 252 個ADC周期 = 21us
* @param 無
* @retval 無
*/
void adc_init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
g_adc_handle.Instance = ADC_ADCX;
g_adc_handle.Init.ContinuousConvMode = ENABLE;
g_adc_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
g_adc_handle.Init.DiscontinuousConvMode = DISABLE;
g_adc_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
g_adc_handle.Init.NbrOfConversion = ADC_CH_NUM;
g_adc_handle.Init.NbrOfDiscConversion = 0;
g_adc_handle.Init.ScanConvMode = ENABLE;
HAL_ADC_Init(&g_adc_handle);
HAL_ADCEx_Calibration_Start(&g_adc_handle);//ADC校準
sConfig.Channel = ADC_ADCX_CH4;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
HAL_ADC_ConfigChannel(&g_adc_handle,&sConfig);
sConfig.Channel = ADC_ADCX_CH5;
sConfig.Rank = 2;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
HAL_ADC_ConfigChannel(&g_adc_handle,&sConfig);
__HAL_LINKDMA(&g_adc_handle, DMA_Handle ,g_dma_adc_handle);
// 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, (uint32_t)g_adc_value, ADC_CH_NUM * ADC_COLL);
// HAL_ADC_Start_DMA(&g_adc_handle,(uint32_t *)g_adc_value,ADC_CH_NUM * ADC_COLL);
}
void adc_dma_init(void)
{
if ((uint32_t)ADC_ADCX_DMACx > (uint32_t)DMA1_Channel7) /* 大于DMA1_Channel7, 則為DMA2的通道了 */
{
__HAL_RCC_DMA2_CLK_ENABLE(); /* DMA2時鐘使能 */
}
else
{
__HAL_RCC_DMA1_CLK_ENABLE(); /* DMA1時鐘使能 */
}
g_dma_adc_handle.Instance = DMA1_Channel1;
g_dma_adc_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;
g_dma_adc_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
g_dma_adc_handle.Init.MemInc = DMA_MINC_ENABLE;
g_dma_adc_handle.Init.Mode = DMA_NORMAL;
g_dma_adc_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
g_dma_adc_handle.Init.PeriphInc = DMA_PINC_DISABLE;
g_dma_adc_handle.Init.Priority = DMA_PRIORITY_MEDIUM;
HAL_DMA_Init(&g_dma_adc_handle);
// __HAL_LINKDMA(&g_adc_handle, DMA_Handle ,g_dma_adc_handle);
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn,1,3);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
// HAL_DMA_Start_IT(&g_dma_adc_handle, (uint32_t)&ADC1->DR, (uint32_t)g_adc_value, ADC_CH_NUM * ADC_COLL);
HAL_ADC_Start_DMA(&g_adc_handle,(uint32_t *)g_adc_value,ADC_CH_NUM * ADC_COLL);
// if (HAL_ADC_Start_DMA(&g_adc_handle, (uint32_t *)g_adc_value, ADC_CH_NUM * ADC_COLL) != HAL_OK)
//{
// // 處理錯誤
// printf("error");
//}
}
/**
* @brief ADC底層驅動,引腳配置,時鐘使能
此函數會被HAL_ADC_Init()調用
* @param hadc:ADC句柄
* @retval 無
*/
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
if(hadc->Instance == ADC_ADCX)
{
GPIO_InitTypeDef GPIO_Initure;
ADC_ADCX_CHY_CLK_ENABLE(); //adc時鐘
ADC_ADCX_CH4_GPIO_CLK_ENABLE(); /* 開啟GPIO時鐘 */
ADC_ADCX_CH5_GPIO_CLK_ENABLE(); /* 開啟GPIO時鐘 */
/* AD采集引腳模式設置,模擬輸入 */
GPIO_Initure.Pin = ADC_ADCX_CH4_GPIO_PIN;
GPIO_Initure.Mode = GPIO_MODE_ANALOG;
GPIO_Initure.Pull = GPIO_PULLUP;
HAL_GPIO_Init(ADC_ADCX_CH4_GPIO_PORT, &GPIO_Initure);
/* AD采集引腳模式設置,模擬輸入 */
GPIO_Initure.Pin = ADC_ADCX_CH5_GPIO_PIN;
GPIO_Initure.Mode = GPIO_MODE_ANALOG;
GPIO_Initure.Pull = GPIO_PULLUP;
HAL_GPIO_Init(ADC_ADCX_CH5_GPIO_PORT, &GPIO_Initure);
//ADC時鐘初始化
RCC_PeriphCLKInitTypeDef adc_clk_init = {0};
adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;
adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;
HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);
}
}
void ADC_ADCX_DMASX_IRQHandler(void)
{
HAL_DMA_IRQHandler(&g_dma_adc_handle);
g_adc_dma_sta = 1; // 標記DMA傳輸完成
}
uint16_t g_adc_val[ADC_CH_NUM];
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
uint32_t temp;
if(hadc->Instance == ADC_ADCX)
{
// print_adc_values();
HAL_ADC_Stop_DMA(hadc);
calc_adc_val(g_adc_val);
HAL_ADC_Start_DMA(&g_adc_handle,(uint32_t *)&g_adc_value,ADC_SUM);
}
}
//void print_adc_values(void)
//{
// // 確保在打印之前進行數據校驗,例如檢查數據個數和有效性
// for (int i = 0; i < ADC_CH_NUM * ADC_COLL; i++)
// {
// // 確認數組中的數據是否有效
// if (g_adc_value[i] != 0) // 例如,不等于0表示有效
// {
// printf("g_adc_value[%d]: %u\r\n", i, g_adc_value[i]);
// }
// }
//}
/**
* @brief 獲取通道ch的轉換值,取times次, 然后平均
* @param ch: 通道號, 0~17
* @retval 通道ch的times次轉換結果平均值
*/
uint32_t adc_get_result_average(uint8_t ch)
{
uint32_t temp_val = 0;
uint16_t t;
for(t = ch; t < ADC_SUM; t += ADC_CH_NUM)
{
temp_val += g_adc_value[t];
}
return temp_val / ADC_COLL;
}
/**
* @brief 計算ADC的平均值(濾波)
* @param * p :存放ADC值的指針地址
* @note 此函數對電壓、溫度、電流對應的ADC值進行濾波
* @retval 無
*/
void calc_adc_val(uint16_t * p)
{
uint32_t temp[ADC_CH_NUM] = {0,0}; /* 定義一個緩存數組 */
int i,j;
for(i = 0; i < ADC_COLL; i++) /* 循環采集ADC_COLL次數 */
{
for(j = 0; j < ADC_CH_NUM; j++) /* 根據ADC通道數循環獲取,并累加 */
{
temp[j] += g_adc_value[j+i*ADC_CH_NUM]; /* 將采集到的ADC值,各通道進行累加 */
}
}
for(j = 0; j < ADC_CH_NUM; j++)
{
temp[j] /= ADC_COLL; /* 獲取平均值 */
p[j] = temp[j]; /* 存到*p */
}
}
/**
****************************************************************************************************
* @file main.c
* @author 正點原子團隊(ALIENTEK)
* @version V1.0
* @date 2020-04-24
* @brief SPI 實驗
* @license Copyright (c) 2020-2032, 廣州市星翼電子科技有限公司
****************************************************************************************************
* @attention
*
* 實驗平臺:正點原子 STM32F103開發板
*
****************************************************************************************************
*/
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./USMART/usmart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./BSP/NORFLASH/norflash.h"
#include "./BSP/SPI/spi.h"
#include "./BSP/ICM42688/icm42688.h"
#include "./BSP/ESP8266USART/esp8266usart.h"
#include "./BSP/ESP8266/esp8266.h"
#include "./BSP/ADC/adc.h"
//int time=50;
int8_t accel1[3];
int16_t accel[3];
int16_t gyro[3];
int16_t adc_result[ADC_CH_NUM];
//uint8_t ret;
uint8_t *frame = NULL;
uint8_t result;
extern uint16_t g_adc_value[ADC_CH_NUM * ADC_COLL] ;
extern uint16_t g_adc_val[ADC_CH_NUM];
extern uint8_t g_adc_dma_sta;
extern ADC_HandleTypeDef g_adc_handle; /* ADC句柄 */
int main(void)
{
HAL_Init(); /* 初始化HAL庫 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 設置時鐘, 72Mhz */
delay_init(72); /* 延時初始化 */
usart_init(115200); /* 串口初始化為115200 */
// usmart_dev.init(72); /* 初始化USMART */
// led_init(); /* 初始化LED */
// key_init(); /* 初始化按鍵 */
spi2_init();
Icm42688_Init();
// ICM42688_Connect();
esp8266_uart_init(115200);
adc_init();
adc_dma_init();
//
// // 等待DMA傳輸完成
// while (!g_adc_dma_sta)
// {
// // 等待DMA傳輸完成
// printf("Waiting for DMA transfer to complete...\r\n");
// }
// // 輸出第一個ADC值
// printf("g_adc_value[0]:%d\r\n", g_adc_value[0]);
// ESP8266_EN(0);
// result = esp8266_Init(115200);
// printf("result:%d\r\n",result);
// result = esp8266_send_at_cmd("AT","OK",500);
// printf("result:%d\r\n",result);
// 連接wifi成功
// result = esp8266_join_ap("xiao","312312312");
// printf("result:%d\r\n",result);
//for(int i = 0; i < 2 ;i++)
//{
// printf("g_adc_value[%d]:%u\r\n",i,g_adc_val[i]);
//}
// printf("wraeyrut");
// printf("g_adc_value");
// printf("x,y:%u\r\n",g_adc_val[0]);
while (1)
{
//多通道ADC轉化,沒有DMA
// uint16_t adcx;
// adcx = adc_get_result(adc_result);
// printf("adcx:%d,adcy:%d,\r\n",adc_result[0],adc_result[1]);
printf("adcx:%d,adcy:%d\r\n",g_adc_val[0],g_adc_val[1]);
// //測試串口3是否正常
// //測試串口3是否正常
// //測試串口3是否正常
// frame = esp8266_uart_rx_get_frame();
// if (frame != NULL) {
// // 處理接收到的數據,這里假設我們要打印接收到的數據
// esp8266_uart_printf("Received: %s\r\n", frame);
// // 處理完之后,重置接收狀態
// esp8266_uart_rx_restart(); // 重新啟動接收
// } else {
// // 如果沒有接收到完整數據,可以選擇處理超時或者其他邏輯
// esp8266_uart_printf("No complete frame received yet.\r\n");
// }
// esp8266_uart_printf("AT\r\n");
// printf("456\r\n");
// delay_ms(1000);
// frame = esp8266_uart_rx_get_frame();
// printf("frame:%s\r\n",frame);
// printf("123\r\n");
//測試ICM42688
// ICM42688_Read_Data(accel,gyro);
// printf("gyro_x:%d gyro_y:%d gyro_z:%d\r\n",gyro[0],gyro[1],gyro[2]);
// printf("accel_x:%d accel_y:%d accel_z:%d\r\n",accel[0],accel[1],accel[2]);
// delay_ms(1000);
}
}
復制代碼
作者:
飛云居士
時間:
2024-10-22 10:00
調整了以下幾點代碼,看可否解決DMA傳輸數據為0的問題。修改點包括:
1. **確保DMA和ADC的初始化順序正確**。
2. **添加調試日志,監控DMA傳輸狀態和數據**。
3. **確保DMA中斷優先級和中斷處理函數工作正常**。
4. **保證ADC DMA啟動后的數據讀取流程正確**。
### 修改后的代碼如下:
```c
#include "./BSP/ADC/adc.h"
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/usart/usart.h"
ADC_HandleTypeDef g_adc_handle; /* ADC句柄 */
DMA_HandleTypeDef g_dma_adc_handle; /* 與ADC關聯的DMA句柄 */
uint8_t g_adc_dma_sta = 0; /* DMA傳輸狀態標志, 0,未完成; 1, 已完成 */
uint16_t g_adc_value[ADC_CH_NUM * ADC_COLL] = {0}; /* 存儲ADC原始值 */
uint16_t g_adc_val[ADC_CH_NUM] = {0}; /* 存儲處理后的ADC平均值 */
/********************************************************************/
/**
* @brief ADC初始化函數
* @retval 無
*/
void adc_init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
g_adc_handle.Instance = ADC_ADCX;
g_adc_handle.Init.ContinuousConvMode = ENABLE;
g_adc_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
g_adc_handle.Init.DiscontinuousConvMode = DISABLE;
g_adc_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
g_adc_handle.Init.NbrOfConversion = ADC_CH_NUM;
g_adc_handle.Init.ScanConvMode = ENABLE;
HAL_ADC_Init(&g_adc_handle);
HAL_ADCEx_Calibration_Start(&g_adc_handle); // ADC校準
sConfig.Channel = ADC_ADCX_CH4;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
HAL_ADC_ConfigChannel(&g_adc_handle, &sConfig);
sConfig.Channel = ADC_ADCX_CH5;
sConfig.Rank = 2;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
HAL_ADC_ConfigChannel(&g_adc_handle, &sConfig);
}
/********************************************************************/
/**
* @brief DMA初始化函數
* @retval 無
*/
void adc_dma_init(void)
{
if ((uint32_t)ADC_ADCX_DMACx > (uint32_t)DMA1_Channel7) /* 大于DMA1_Channel7, 則為DMA2的通道了 */
{
__HAL_RCC_DMA2_CLK_ENABLE(); /* DMA2時鐘使能 */
}
else
{
__HAL_RCC_DMA1_CLK_ENABLE(); /* DMA1時鐘使能 */
}
g_dma_adc_handle.Instance = DMA1_Channel1;
g_dma_adc_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;
g_dma_adc_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
g_dma_adc_handle.Init.MemInc = DMA_MINC_ENABLE;
g_dma_adc_handle.Init.Mode = DMA_CIRCULAR; // 設置為循環模式,確保DMA持續工作
g_dma_adc_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
g_dma_adc_handle.Init.PeriphInc = DMA_PINC_DISABLE;
g_dma_adc_handle.Init.Priority = DMA_PRIORITY_MEDIUM;
HAL_DMA_Init(&g_dma_adc_handle);
__HAL_LINKDMA(&g_adc_handle, DMA_Handle, g_dma_adc_handle); // 關聯DMA和ADC
}
/********************************************************************/
/**
* @brief DMA傳輸完成中斷處理函數
* @retval 無
*/
void ADC_ADCX_DMASX_IRQHandler(void)
{
HAL_DMA_IRQHandler(&g_dma_adc_handle);
g_adc_dma_sta = 1; // 標記DMA傳輸完成
}
/********************************************************************/
/**
* @brief ADC轉換完成回調函數
* @retval 無
*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
if (hadc->Instance == ADC_ADCX)
{
HAL_ADC_Stop_DMA(hadc); // 停止DMA,防止數據被覆蓋
calc_adc_val(g_adc_val); // 計算ADC平均值
g_adc_dma_sta = 1; // 標記DMA傳輸完成
HAL_ADC_Start_DMA(hadc, (uint32_t *)g_adc_value, ADC_CH_NUM * ADC_COLL); // 重新啟動DMA
}
}
/********************************************************************/
/**
* @brief 計算ADC的平均值(濾波)
* @param *p : 存放ADC值的指針地址
* @retval 無
*/
void calc_adc_val(uint16_t *p)
{
uint32_t temp[ADC_CH_NUM] = {0}; /* 緩存數組 */
for (int i = 0; i < ADC_COLL; i++)
{
for (int j = 0; j < ADC_CH_NUM; j++)
{
temp[j] += g_adc_value[j + i * ADC_CH_NUM]; /* 累加 */
}
}
for (int j = 0; j < ADC_CH_NUM; j++)
{
p[j] = temp[j] / ADC_COLL; /* 計算平均值 */
}
}
int main(void)
{
HAL_Init(); /* 初始化HAL庫 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 設置時鐘, 72Mhz */
delay_init(72); /* 延時初始化 */
usart_init(115200); /* 串口初始化為115200 */
adc_init(); // 初始化ADC
adc_dma_init(); // 初始化DMA
// 啟動DMA
if (HAL_ADC_Start_DMA(&g_adc_handle, (uint32_t *)g_adc_value, ADC_CH_NUM * ADC_COLL) != HAL_OK)
{
printf("ADC DMA start failed\r\n");
}
while (1)
{
if (g_adc_dma_sta) // DMA傳輸完成
{
g_adc_dma_sta = 0; // 重置標志位
printf("ADC Value Channel 1: %d, Channel 2: %d\r\n", g_adc_val[0], g_adc_val[1]);
}
}
}
```
### 程序修改了:
1. **DMA初始化**:確保正確初始化DMA,并關聯到ADC句柄。
2. **DMA模式**:將DMA模式設置為 `DMA_CIRCULAR`,這樣DMA會持續工作,而不需要手動重新啟動。
3. **中斷處理**:在 `ADC_ADCX_DMASX_IRQHandler()` 中設置DMA傳輸完成標志位,并在 `HAL_ADC_ConvCpltCallback()` 中處理傳輸完成的邏輯。
4. **ADC轉換完成處理**:在回調函數 `HAL_ADC_ConvCpltCallback()` 中停止DMA、計算ADC平均值,并重新啟動DMA。
5. **主循環**:通過輪詢 `g_adc_dma_sta` 檢測DMA傳輸完成,并在主循環中打印ADC轉換后的數據。
### 調試提示:
- 在 `HAL_ADC_Start_DMA()` 后面添加錯誤處理,確保DMA和ADC啟動正常。
- 你可以通過串口日志查看 `g_adc_val[]` 是否有正確的值輸出。如果還存在問題,可以進一步調試DMA的中斷是否正確觸發。
歡迎光臨 (http://m.zg4o1577.cn/bbs/)
Powered by Discuz! X3.1
主站蜘蛛池模板:
在线播放一区二区三区
|
日日操操
|
九九伊人sl水蜜桃色推荐
|
精国产品一区二区三区
|
一本色道久久综合亚洲精品高清
|
日韩视频观看
|
日韩在线不卡
|
久久成人免费视频
|
av天天干
|
偷拍第一页
|
亚洲一区二区三区国产
|
激情婷婷
|
国产成人精品久久二区二区
|
www.日本在线播放
|
一级片在线免费播放
|
福利视频1000
|
天堂资源
|
国产欧美一区二区三区日本久久久
|
欧美精品91
|
国产精品久久久久久久久污网站
|
先锋资源网站
|
国产一区91在线
|
国产精品成人在线观看
|
欧美综合一区二区
|
国产精品区二区三区日本
|
欧美一级欧美一级在线播放
|
av在线免费观看网站
|
午夜电影福利
|
国产成人精品亚洲日本在线观看
|
日韩三区
|
91视频久久久久
|
黄色成人在线观看
|
三级黄色大片网站
|
hitomi一区二区三区精品
|
欧美日韩在线一区
|
天天干,夜夜操
|
九九亚洲
|
国产日韩欧美中文字幕
|
久久99深爱久久99精品
|
一区二区三区在线播放
|
麻豆国产一区二区三区四区
|