//software_triger_adc.c
#include "adc_sample.h"
/*********<Variable>********/
uint8_t g_dmaFinish = 0;//DMA传输完成
uint8_t g_halfDmaFinish = 0; //DMA传输半完成
uint8_t g_dmaTransError = 0; //DMA传输错误
uint16_t g_ADCValueBuffer[DMA_TRANSFER_NUM+1]; //存放数据 4
float adc_avge[4]; //4个通道存放 设置成float 实际电压
uint32_t g_timerCnt = 0;
uint16_t g_regularAverageSampleValue = 0; //规则组采样平均值
uint16_t g_injectAverageSampleValue = 0; //注入组采样平均值
uint16_t g_adcInjectValue[4];
uint8_t g_AMOFlag = 0;//模拟看门狗事件标志
/*
注意:EOC标志写0或读取ADC_RDR都会清除该标志位。
在进行debug时,如果有打开memory窗口或打开ADC寄存器。
该标志会被debug清除。
*/
/**
* ADC_DMACallback
*
* @param[in] void
* @return void
*
* @brief ADC 中断回调函数。
*/
void ADC_Callback(void *device, uint32_t wpara, uint32_t lpara)
{
// if (wpara & ADC_STR_IEOC_Msk) //注入组中断标志
// {
// g_IEOCFlag = 1;
// g_adcInjectValue[0] = ADC_GetInjectData(ADC0, 0);
// g_adcInjectValue[1] = ADC_GetInjectData(ADC0, 1);
// g_adcInjectValue[2] = ADC_GetInjectData(ADC0, 2);
// g_adcInjectValue[3] = ADC_GetInjectData(ADC0, 3);
// }
// if (wpara & ADC_STR_EOC_Msk) //规则组中断标志
// {
// g_EOCFlag = 1;
// }
// if (wpara & ADC_STR_AMO_Msk) //模拟监控中断标志
// {
// g_AMOFlag = 1;
// }
}
/**
* ADC_DMACallback
*
* @param[in] wpara:dmaChannelStatus
* lpara:0
* @return 0
*
* @brief ADC DMA中断回调函数。
*/
void ADC_DMACallback(void *device, uint32_t wpara, uint32_t lpara) //四个通道采集完一次在用
{
/*
wparam为DMA通道状态,状态含义可参考CHANNELx_STATUS寄存器,
CHANNELx_STATUS[2] 传输错误
CHANNELx_STATUS[1] 半传输完成(相对设置的transferNum,如果半传输中断有使能,transferNum设为6,则DATA_TRANS_NUM为3时产生中断,进入回调)
CHANNELx_STATUS[0] 传输完成
*/
if ((wpara & 0x01) == 0x1)
{
g_dmaFinish = 1;
// printf("123123\r\n");
}
if ((wpara & 0x02) == 0x2)
{
g_halfDmaFinish = 1;
}
if ((wpara & 0x04) == 0x4)
{
g_dmaTransError = 1;
}
}
/**
* ADC_DMAInit
*
* @param[in] void
* @return void
*
* @brief ADC DMA初始化,配置DMA相关参数。
*/
void ADC_DMAInit(void)
{
uint32_t tmpMemStartAddr = (uint32_t)&g_ADCValueBuffer[0];
uint32_t tmpMemEndAddr = (uint32_t)&g_ADCValueBuffer[DMA_TRANSFER_NUM+1];
DMA_ConfigType tmpDMAConfig;
memset(&tmpDMAConfig, 0x00, sizeof(DMA_ConfigType));
tmpDMAConfig.memStartAddr = tmpMemStartAddr; //设置DMA开始地址
tmpDMAConfig.memEndAddr = tmpMemEndAddr;//设置DMA结束地址
tmpDMAConfig.periphStartAddr = (uint32_t)(&(ADC0->RDR)); ///<Move ADC DR to memory
tmpDMAConfig.channelEn = ENABLE; ///<使能DMAx通道
tmpDMAConfig.finishInterruptEn = ENABLE; ///<使能DMA传输完成中断
tmpDMAConfig.halfFinishInterruptEn = DISABLE; ///<去能DMA半传输完成中断
tmpDMAConfig.errorInterruptEn = ENABLE; ///<使能DMA传输错误中断
tmpDMAConfig.channelPriority = DMA_PRIORITY_VERY_HIGH;//<设置DMA通道优先级,0~3 :优先级由低到高
tmpDMAConfig.circular = DISABLE; //<使能循环模式,如果只想工作一次,设为0即可。
tmpDMAConfig.direction = DMA_READ_FROM_PERIPH; //<0: 从外设读取,1:从存储器读取
tmpDMAConfig.MEM2MEM = DISABLE;//0:在非存储器与存储器之间传输,1:在存储器与存储器之间传输
tmpDMAConfig.memByteMode = DMA_MEM_BYTE_MODE_1TIME; ///<MEM字分割传输数,0:32-bit,1:16-bit[15:0]; 2:16-bit[23:16][7:0];3:8-bit。详情可参考AC781X芯片手册 表20-2 可编程数据宽度&数据对齐
tmpDMAConfig.memIncrement = ENABLE; ///<1:MEM地址增加
tmpDMAConfig.periphIncrement = DISABLE; ///<0:外设地址固定
tmpDMAConfig.memSize = DMA_MEM_SIZE_16BIT; //<0:8-bit,1:16-bit,2:32-bit
tmpDMAConfig.periphSize = DMA_PERIPH_SIZE_16BIT; //<0:8-bit,1:16-bit,2:32-bit
tmpDMAConfig.transferNum = DMA_TRANSFER_NUM; //<DMA通道传输长度
tmpDMAConfig.periphSelect = DMA_PEPIRH_ADC0; //外设选择
tmpDMAConfig.callBack = ADC_DMACallback; ///<设置DMA中断回调
DMA_Init(DMA0_CHANNEL0, &tmpDMAConfig);
NVIC_EnableIRQ(DMA0_CHANNEL0_IRQn); ///<使能DMA1中断请求
}
void CTU_Config(void)
{
CTU_ConfigType ctuConfig;
memset(&ctuConfig, 0x00, sizeof(ctuConfig));
ctuConfig.uart0RxFilterEn = DISABLE; //去能UART0_RX滤波
ctuConfig.rtcCaptureEn = DISABLE; //去能RTC捕获
ctuConfig.acmpCaptureEn = DISABLE; //去能ACMP捕获
ctuConfig.uart0RxCaptureEn = DISABLE; //去能UART0_RX捕获
ctuConfig.uartTxModulateEn = DISABLE; //去能UART0_TX调制
ctuConfig.clkPsc = CTU_CLK_PRESCALER_1; //分频
ctuConfig.adcRegularTriggerSource = CTU_TRIGGER_ADC_TIMER_CH0_OVERFLOW; //Timer0触发ADC规则组采样。
ctuConfig.delay0Time = 0; //触发延迟
CTU_Init(&ctuConfig);
}
#define BaseVref 1.0f
#define smpMax 4.5f
void TIMER_Callback(void *device, uint32_t wpara, uint32_t lpara) //定时器中断10ms采集一次
{
int i;
static flaot x_n[4]={0.0f}; //0.0f 浮点型(float)
if (TIMER_CHANNEL0 == device) //定时器通道
{
g_timerCnt++;
if(g_timerCnt==50) // 计数器加到50 到了500ms=0.5s采集一次
{
g_timerCnt=0; //清零
for(i=0;i<1;i++) //每个通道1次
{
adc_avge[0]=g_ADCValueBuffer[0]*4.8f/(4096.0f); //基准电压4.8V 实际电压变float
adc_avge[1]=g_ADCValueBuffer[1]*4.8f/(4096.0f);
adc_avge[2]=g_ADCValueBuffer[2]*4.8f/(4096.0f);
adc_avge[3]=g_ADCValueBuffer[3]*4.8f/(4096.0f);
}
if(u_rx_flag==1)
{
u_rx_flag=0;
printf("系数已更新\r\n");
for(i=0;i<4;i++)
{
if(adc_avge[i]==0)
{
printf("x_n%d : %f, adc_avge%d %f,"i+1,x_n[i],adc_avge[i]);
}
else
{
x_n[i]=(float)(BaseVref/((float)(adc_avge[i])));
printf("x_n%d : %f,adc_avge%d %0.2f,"i+1,x_n[i],i+1,adc_avge[i]);
}
}
printf("\r\n");
}
for(i=0;i<4;i++)
{
printf("Sample%d : %0.2f, %0.2f, %0.2f,"i+1,(adc_avge[i]),x_n[i],(adc_avge[i]*x_n[i]));
adc_avge[i]=0;
}
printf("\r\n");
printf("end\r\n");
}
ADC_DMAInit();
}
}
/**
* TIMER0_Init
*
* @param[in] void
* @return void
*
* @brief TIMER0初始化
*/
void TIMER0_Init(void)
{
TIMER_ConfigType timerConfig = {0};
timerConfig.periodValue = Delay10ms;//10ms定时
timerConfig.interruptEn = ENABLE;//使能中断
timerConfig.linkModeEn = DISABLE;//级联模式去能
timerConfig.callBack = TIMER_Callback;//设置中断回调函数
timerConfig.timerEn = ENABLE;//使能定时器
TIMER_Init(TIMER_CHANNEL0, &timerConfig);
}
/**
* ADC_init
*
* @param[in] void
* @return void
*
* @brief 初始化ADC,配置ADC参数。
*/
void ADC_init()
{
ADC_ConfigType tempAdcConfig;
ADC_ConfigType* adcConfig;
adcConfig = &tempAdcConfig;
//配置PINMUX
GPIO_SetFunc(GPIOA, GPIO_PIN11, GPIO_FUN2);///<ADC_IN11 Analog function enable
GPIO_SetFunc(GPIOA, GPIO_PIN10, GPIO_FUN2);///<ADC_IN10 Analog function enable
GPIO_SetFunc(GPIOA, GPIO_PIN9, GPIO_FUN2);///<ADC_IN9 Analog function enable
GPIO_SetFunc(GPIOA, GPIO_PIN8, GPIO_FUN2);///<ADC_IN8 Analog function enable
adcConfig->clkPsc = ADC_CLK_PRESCALER_1; ///<Set ADC Clk = 24M/2/(0+1)
adcConfig->scanModeEn = ENABLE; //扫描模式 4个通道
adcConfig->continousModeEn = DISABLE; //连续模式 定时器触发
adcConfig->regularDiscontinousModeEn = DISABLE; //1:打开规则组间断转换模式
adcConfig->injectDiscontinousModeEn = DISABLE; //1:打开注入组间断转换模式
adcConfig->injectAutoModeEn = DISABLE; //1:自动注入模式
adcConfig->intervalModeEn = DISABLE; //1:注入组为间隔转换模式
adcConfig->regularDiscontinousNum = 0; //
adcConfig->EOCInterruptEn = ENABLE; //EOC中断使能
adcConfig->IEOCInterruptEn = ENABLE; //IEOC中断使能
adcConfig->interruptEn = DISABLE; //中断使能
adcConfig->regularDMAEn = ENABLE; //使能ADC DMA
adcConfig->regularTriggerMode = ADC_TRIGGER_EXTERNAL;//ADC触发源,外部触发 TIM
adcConfig->injectTriggerMode = ADC_TRIGGER_INTERNAL; //ADC触发源,内部触发
adcConfig->regularSequenceLength = 4; //规则组长度设为4
adcConfig->injectSequenceLength = 0; //注入组长度设为0
adcConfig->dataAlign = ADC_DATA_ALIGN_RIGHT; //右对齐
adcConfig->callBack = ADC_Callback; //回调
adcConfig->powerMode = ADC_POWER_ON; //上电
ADC_Init(ADC0, adcConfig); //<ADC works Mode Config
/*
ADC转换率计算公式:
转换时间= 采样时间+转换时间+同步时间 采样时间越大,周期越大,通道才能全部转换完
转换时间= (SPT+12)/ADC模块时钟频率+5/APB时钟频率
备注:
1.同步时间为5个APB CLK。
2.ADC时钟频率 = APB时钟频率 /(分频系数+1)
*/
//215 转换时间引起通道号不对?????????????
//规则组通道设置 ADC_SPT_CLK_64
ADC_SetRegularGroupChannel(ADC0, ADC_CH_0, ADC_SPT_CLK_64, 0);
ADC_SetRegularGroupChannel(ADC0, ADC_CH_1, ADC_SPT_CLK_64, 1); //采样&转换时间= (7+12)/24000000 + 5/24000000 = 1us
ADC_SetRegularGroupChannel(ADC0, ADC_CH_2, ADC_SPT_CLK_64, 2); //采样&转换时间= (64+12)/24000000 + 5/24000000 = 1us
ADC_SetRegularGroupChannel(ADC0, ADC_CH_3, ADC_SPT_CLK_64, 3);
//规则组DMA初始化
ADC_DMAInit(); //ADC DMA初始化
}
//void sampleValueDeal(void)
//{
// int i;
// //ZE03 H2输出
// for(i = 0; i < UART_RX_BUFF_LENGTH; i++)
// {
// if(i == UART_RX_BUFF_LENGTH -1)
// printf("%x\r\n", g_uartRxDataBuff[i]);
// else
// printf("%x ", g_uartRxDataBuff[i]);
// }
// printf("gasConc = %d\r\n", gasConcentration);
// // ADC_DMAInit();
//}
/**
* ADC_SampleSoftwareTrigerADC
*
* @param[in] void
* @return void
*
* @brief Timer定时触发规则组ADC_CHANNEL0单次采样。
*/
void ADC_SampleSoftwareTrigerADC(void)
{
CTU_Config();
ADC_init();
TIMER0_Init();
while(1)
{
//每次转换数据清零
memset(g_ADCValueBuffer, 0x00, sizeof(g_ADCValueBuffer));
ADC_SoftwareStartRegularConvert(ADC0); ///软件触发规则组采样
//udelay(4);//需要采样8个通道,延时8us以保证数据采样完成
//sampleValueDeal();
LED3_TOGGLE;
LED2_TOGGLE;
mdelay(1000); //延时1s 1000ms
}
}
//adc_sample.h
#ifndef ADC_SAMPLE_H_
#define ADC_SAMPLE_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "string.h"
#include "ac780x_adc.h"
#include "ac780x_adc_reg.h"
#include "ac780x_gpio.h"
#include "ac780x.h"
#include "ac780x_debugout.h"
#include "ac780x_dma.h"
#include "ac780x_ctu.h"
#include "ac780x_timer.h"
#include "ac780x_pwm.h"
#include "gpio.h"
#define Delay5us (APB_BUS_FREQ/200000-1)
#define Delay10ms (APB_BUS_FREQ/200-1)*2
#define Delay1s (APB_BUS_FREQ-1)
#define DMA_TRANSFER_NUM 4
#define UART_RX_BUFF_LENGTH 4
#define HEX_VALUE 0x1A //串口发送指令
extern uint8_t u_rx_flag; //标志位
extern uint8_t g_uartRxDataBuff[UART_RX_BUFF_LENGTH];
void ADC_DMACallback(void *device, uint32_t wpara, uint32_t lpara);
extern uint16_t g_ADCValueBuffer[DMA_TRANSFER_NUM+1];
extern uint16_t gasConcentration;//气体浓度
void ADC_SampleSoftwareTrigerADC(void);
void InitUart1(void);
void InitUart2(void);
#ifdef __cplusplus
}
#endif
#endif
//"ac780x_debugout.c
/*!
* @file ac780x_debugout.c
*
* @brief This file provides debug information output integration functions.
*
*/
/* =========================================== Includes =========================================== */
#include "ac780x.h"
#include "ac780x_gpio.h"
#include "ac780x_uart.h"
#include "ac780x_uart_reg.h"
#include "adc_sample.h"
/* ============================================ UART2 ============================================ */
#define MAX_DEBUG_BUFF_SIZE 100 /* define uart max receive buffer size */
#define DEBUG_UART UART2 /* define uart2 for debug output */
#define DEBUG_UART_IRQ UART2_IRQn /* define uart2 interrupt vector */
#define DEBUG_UART_CLK CLK_UART2 /* define uart2 ckgen clock value */
#define DEBUG_UART_SRST SRST_UART2 /* define uart2 ckgen reset value */
#define DEBUG_UART_SMP 16.0F
#define DEBUG_UART_BAUDRATE 115200.0F
#define DEBUG_UART_TX GPIOB,GPIO_PIN9 /* define uart2 tx gpio */
#define DEBUG_UART_RX GPIOB,GPIO_PIN10 /* define uart2 rx gpio */
/* ============================================ UART1 ============================================ */
//#define DEBUG_UART1 UART1 /* define uart1 for debug output */
//#define DEBUG_UART1_IRQ UART1_IRQn /* define uart1 interrupt vector */
//#define DEBUG_UART1_CLK CLK_UART1 /* define uart1 ckgen clock value */
//#define DEBUG_UART1_SRST SRST_UART1 /* define uart1 ckgen reset value */
//#define DEBUG_UART1_SMP 16.0F
//#define DEBUG_UART1_BAUDRATE 9600.0F
//#define DEBUG_UART_TX GPIOA,GPIO_PIN4 /* define uart1 tx gpio */
//#define DEBUG_UART_RX GPIOA,GPIO_PIN5 /* define uart1 rx gpio */
/* =========================================== Typedef ============================================ */
/* ========================================== Variables =========================================== */
/* debug uart receive buf */
//uint8_t g_debugBuff[MAX_DEBUG_BUFF_SIZE] = {0};
uint8_t g_uartRxDataBuff[UART_RX_BUFF_LENGTH]={0}; //接收数组
uint16_t g_uartRxDataIndex;
uint8_t u_rx_flag= 0;
uint8_t *g_uartTxDataPoint;
uint16_t g_uartTxDataLength;
uint16_t g_uartTxDataIndex;
uint8_t receiveStart;
uint16_t gasConcentration;//气体浓度
float resolution;//分辨率
/* debug init flag */
static uint8_t s_debugInit = 0;
/* define std FILE struct */
struct __FILE
{
int handle;
};
/* refine stdout,stdin,stderr */
FILE __stdout;
FILE __stdin;
FILE __stderr;
/* ==================================== Functions declaration ===================================== */
/* ====================================== Functions define ======================================== */
/*!
* @brief refine _sys_exit
*
* @param[in] x: no use
* @return always 0
*/
int _sys_exit(int x)
{
x = x;
return 0;
}
/*!
* @brief refine _ttywrch
*
* @param[in] x: no use
* @return always 0
*/
int _ttywrch(int x)
{
x = x;
return 0;
}
/*!
* @brief put a char to UART
*
* @param[in] f: file pointer for the std input
* @param[in] ch: the char to put
* @return return the char of be put
*/
int fputc(int ch, FILE *f)
{
if (s_debugInit)
{
UART_SendData(DEBUG_UART, ch);
}
return ch;
}
/*!
* @brief get a char
*
* @param[in] f: file pointer for the std input
* @return -1: not get char, other: the char get from UART
*/
int fgetc(FILE* f)
{
int ch = -1;
if (s_debugInit)
{
if (UART_RxIsDataReady(DEBUG_UART))
{
ch = UART_ReceiveData(DEBUG_UART);
}
}
return ch;
}
/*!
* @brief set the debug out is invalid
*
* @param[in] none
* @return none
*/
void DeinitDebug(void)
{
s_debugInit = 0;
}
/*!
* @brief init debug out , and set the debug out is valid
*
* @param[in] none
* @return none
*/
void InitDebug(void) //串口2
{
#ifdef DEBUG_CMD_INTERRUPT
NVIC_SetPriority(DEBUG_UART_IRQ, 3);
NVIC_ClearPendingIRQ(DEBUG_UART_IRQ);
NVIC_EnableIRQ(DEBUG_UART_IRQ);
#endif
GPIO_SetFunc(DEBUG_UART_TX, GPIO_FUN3);
GPIO_SetFunc(DEBUG_UART_RX, GPIO_FUN3);
CKGEN_Enable(DEBUG_UART_CLK, ENABLE);
CKGEN_SoftReset(DEBUG_UART_SRST, ENABLE);
UART_SetDivisor(DEBUG_UART, (float)APB_BUS_FREQ / DEBUG_UART_SMP / DEBUG_UART_BAUDRATE);
UART_SetDataBits(DEBUG_UART, UART_WORD_LEN_8BIT);
UART_SetStopBit(DEBUG_UART, UART_STOP_1BIT);
UART_EnableTX(DEBUG_UART, ENABLE);
UART_EnableRX(DEBUG_UART, ENABLE);
UART_Set2ByteFIFO(DEBUG_UART, ENABLE);
UART_SetInterruptEn(DEBUG_UART, 9);
s_debugInit = 1;
}
/**
* UartEventCallback
*
* @param[in] device: UART_Type pointer
* @param[in] wpara: UART lsr0 register
* @param[in] lpara: UART lsr1 register
* @return none
*
* @brief uart receive handle
*/
static void UartEventCallback(void *device, uint32_t wpara, uint32_t lpara) //串口2
{
uint8_t volatile data = 0;
UART_Type *uart_Device = (UART_Type *)device;
/*rx interrupt*/ //接收
if ((uart_Device->IER & UART_IER_ERXNE_Msk) && (wpara & UART_LSR0_DR_Msk))
{
uart_Device->RBR =g_uartRxDataBuff[g_uartRxDataIndex++];
u_rx_flag = 1; //标志位为1说明接收到数据
data = uart_Device->RBR; //接收数据寄存器
// if(data == 0xff)//接收到起始位
// receiveStart = 1;
// if(receiveStart == 1)
g_uartRxDataBuff[g_uartRxDataIndex++] = data;
/*
Tx="123456" 字符串
g_uartRxDataBuff = "123456"
'1' = 49
*********接收字节数不对??************
*/
// if (g_uartRxDataIndex >= UART_RX_BUFF_LENGTH)
{
g_uartRxDataIndex = 0;
// //receiveStart = 0;
// if((g_uartRxDataBuff[0] == 0x1A)&&(g_uartRxDataBuff[1] == 0x07))
// (g_uartRxDataBuff[2] == 0xF5)&&(g_uartRxDataBuff[3] == 0x03))
//{
// if(g_uartRxDataBuff[5] == 0x00)
// resolution = 1;
// else if(g_uartRxDataBuff[5] == 0x01)
// resolution = 0.1;
// else if(g_uartRxDataBuff[5] == 0x02)
// resolution = 0.2;
// gasConcentration = (g_uartRxDataBuff[2] * 256 + g_uartRxDataBuff[3] - 200) * resolution;
// }
}
}
/*tx interrupt*/ //串口发送
// if ((uart_Device->IER & UART_IER_ETXE_Msk) && (wpara & UART_LSR0_THRE_Msk))
// {
// uart_Device->RBR = g_uartTxDataPoint[g_uartTxDataIndex++];
// if (g_uartTxDataIndex >= g_uartTxDataLength) //
// {
// UART_SetTXEInterrupt(device, DISABLE); ///<发送最后一个字节时关闭发送空中断
// }
// }
}
void InitUart2(void) //串口2
{
UART_ConfigType uartConfig = {0};
//set pin mux
GPIO_SetFunc(GPIOA, GPIO_PIN9, GPIO_FUN3);
GPIO_SetFunc(GPIOA, GPIO_PIN10, GPIO_FUN3);
uartConfig.baudrate = 115200;
uartConfig.dataBits = UART_WORD_LEN_8BIT;
uartConfig.stopBits = UART_STOP_1BIT;
uartConfig.parity = UART_PARI_NO;
uartConfig.fifoByteEn = ENABLE; //<must enable fifoByte when use DMA
uartConfig.dmaEn = UART_DMA_TXRX_EN;
uartConfig.callBack = UartEventCallback; //<uart2 interrupt callback
UART_Init(UART2, &uartConfig);
UART_SetRXNEInterrupt(UART2, ENABLE);
///Enable UARTx interrupt
NVIC_SetPriority(UART2_IRQn, 3);
NVIC_ClearPendingIRQ(UART2_IRQn);
NVIC_EnableIRQ(UART2_IRQn);
}
/main.c
#include "adc_sample.h"
#include "uart.h"
/**
* main
*
* @param[in] none
* @return 0: success, other: error value
*
* @brief
*/
int main(void)
{
InitDelay();
InitDebug(); //串口2
InitUart2();
//InitUart1(); //串口1
GPIO_LedInit();
printf("\r\nAC7801x: ADC_Sample\r\n");
ADC_SampleSoftwareTrigerADC();
}
ADC采集数据,串口发送一个指令,就需要求比例系数(不变),比例系数=1/采集的电压(float型),以后都是采集的数据*比例系数=修正电压(1左右)。
于 2024-04-09 16:37:04 首次发布