- 打卡等级:初来乍到
- 打卡总天数:7
- 最近打卡:2026-02-23 11:11:05
已绑定手机
注册会员
- 积分
- 53
|
目前遇到的问题:加入DMA_ADC后串口过段时间(大约3~5分钟不等)就会不能收发数据,另外会随机的写modbus寄存器数组的信息,去掉DMA_ADC的函数调用后恢复正常。 这期间我设置过堆栈,将堆栈空间更改为IDATALEN EQU 7FH,会好一些,但更改其他数值无太大影响。 补充说明:串口2 串口3 串口4四路串口做RS485独立通讯,time0:做100us中断并将中断优先级开到最高(作为串口接收超时检测),串口优先级开到较高。 DMA接收中断优先级开到最低。 希望各位大神可以帮忙分析下原因,已经卡柱好几天,找不到解决方法。
以下是相关代码
STARTUP.A51
$NOMOD51
;------------------------------------------------------------------------------
; This file is part of the C51 Compiler package
; Copyright (c) 1988-2005 Keil Elektronik GmbH and Keil Software, Inc.
; Version 8.01
;
; *** <<< Use Configuration Wizard in Context Menu >>> ***
;------------------------------------------------------------------------------
; STARTUP.A51: This code is executed after processor reset.
;
; To translate this file use A51 with the following invocation:
;
; A51 STARTUP.A51
;
; To link the modified STARTUP.OBJ file to your application use the following
; Lx51 invocation:
;
; Lx51 your object file list, STARTUP.OBJ controls
;
;------------------------------------------------------------------------------
;
; User-defined <h> Power-On Initialization of Memory
;
; With the following EQU statements the initialization of memory
; at processor reset can be defined:
;
; <o> IDATALEN: IDATA memory size <0x0-0x100>
; <i> Note: The absolute start-address of IDATA memory is always 0
; <i> The IDATA space overlaps physically the DATA and BIT areas.
IDATALEN EQU 7FH
;
; <o> XDATASTART: XDATA memory start address <0x0-0xFFFF>
; <i> The absolute start address of XDATA memory
XDATASTART EQU 0
;
; <o> XDATALEN: XDATA memory size <0x0-0xFFFF>
; <i> The length of XDATA memory in bytes.
XDATALEN EQU 0x2000
;
; <o> PDATASTART: PDATA memory start address <0x0-0xFFFF>
; <i> The absolute start address of PDATA memory
PDATASTART EQU 0H
;
; <o> PDATALEN: PDATA memory size <0x0-0xFF>
; <i> The length of PDATA memory in bytes.
PDATALEN EQU 0H
;
;</h>
;------------------------------------------------------------------------------
;
;<h> Reentrant Stack Initialization
;
; The following EQU statements define the stack pointer for reentrant
; functions and initialized it:
;
; <h> Stack Space for reentrant functions in the SMALL model.
; <q> IBPSTACK: Enable SMALL model reentrant stack
; <i> Stack space for reentrant functions in the SMALL model.
IBPSTACK EQU 0 ; set to 1 if small reentrant is used.
; <o> IBPSTACKTOP: End address of SMALL model stack <0x0-0xFF>
; <i> Set the top of the stack to the highest location.
IBPSTACKTOP EQU 0xFF +1 ; default 0FFH+1
; </h>
;
; <h> Stack Space for reentrant functions in the LARGE model.
; <q> XBPSTACK: Enable LARGE model reentrant stack
; <i> Stack space for reentrant functions in the LARGE model.
XBPSTACK EQU 0 ; set to 1 if large reentrant is used.
; <o> XBPSTACKTOP: End address of LARGE model stack <0x0-0xFFFF>
; <i> Set the top of the stack to the highest location.
XBPSTACKTOP EQU 0x1FFF +1 ; default 0FFFFH+1
; </h>
;
; <h> Stack Space for reentrant functions in the COMPACT model.
; <q> PBPSTACK: Enable COMPACT model reentrant stack
; <i> Stack space for reentrant functions in the COMPACT model.
PBPSTACK EQU 0 ; set to 1 if compact reentrant is used.
;
; <o> PBPSTACKTOP: End address of COMPACT model stack <0x0-0xFFFF>
; <i> Set the top of the stack to the highest location.
PBPSTACKTOP EQU 0xFF00 +1 ; default 0FFH+1
; </h>
;</h>
;------------------------------------------------------------------------------
;
; Memory Page for Using the Compact Model with 64 KByte xdata RAM
; <e>Compact Model Page Definition
;
; <i>Define the XDATA page used for PDATA variables.
; <i>PPAGE must conform with the PPAGE set in the linker invocation.
;
; Enable pdata memory page initalization
PPAGEENABLE EQU 0 ; set to 1 if pdata object are used.
;
; <o> PPAGE number <0x0-0xFF>
; <i> uppermost 256-byte address of the page used for PDATA variables.
PPAGE EQU 0
;
; <o> SFR address which supplies uppermost address byte <0x0-0xFF>
; <i> most 8051 variants use P2 as uppermost address byte
PPAGE_SFR DATA 0A0H
;
; </e>
;------------------------------------------------------------------------------
; Standard SFR Symbols
ACC DATA 0E0H
B DATA 0F0H
SP DATA 81H
DPL DATA 82H
DPH DATA 83H
NAME ?C_STARTUP
?C_C51STARTUP SEGMENT CODE
?STACK SEGMENT IDATA
RSEG ?STACK
DS 1
EXTRN CODE (?C_START)
PUBLIC ?C_STARTUP
CSEG AT 0
?C_STARTUP: LJMP STARTUP1
RSEG ?C_C51STARTUP
STARTUP1:
IF IDATALEN <> 0
MOV R0,#IDATALEN - 1
CLR A
IDATALOOP: MOV @R0,A
DJNZ R0,IDATALOOP
ENDIF
IF XDATALEN <> 0
MOV DPTR,#XDATASTART
MOV R7,#LOW (XDATALEN)
IF (LOW (XDATALEN)) <> 0
MOV R6,#(HIGH (XDATALEN)) +1
ELSE
MOV R6,#HIGH (XDATALEN)
ENDIF
CLR A
XDATALOOP: MOVX @DPTR,A
INC DPTR
DJNZ R7,XDATALOOP
DJNZ R6,XDATALOOP
ENDIF
IF PPAGEENABLE <> 0
MOV PPAGE_SFR,#PPAGE
ENDIF
IF PDATALEN <> 0
MOV R0,#LOW (PDATASTART)
MOV R7,#LOW (PDATALEN)
CLR A
PDATALOOP: MOVX @R0,A
INC R0
DJNZ R7,PDATALOOP
ENDIF
IF IBPSTACK <> 0
EXTRN DATA (?C_IBP)
MOV ?C_IBP,#LOW IBPSTACKTOP
ENDIF
IF XBPSTACK <> 0
EXTRN DATA (?C_XBP)
MOV ?C_XBP,#HIGH XBPSTACKTOP
MOV ?C_XBP+1,#LOW XBPSTACKTOP
ENDIF
IF PBPSTACK <> 0
EXTRN DATA (?C_PBP)
MOV ?C_PBP,#LOW PBPSTACKTOP
ENDIF
MOV SP,#?STACK-1
; This code is required if you use L51_BANK.A51 with Banking Mode 4
;<h> Code Banking
; <q> Select Bank 0 for L51_BANK.A51 Mode 4
#if 0
; <i> Initialize bank mechanism to code bank 0 when using L51_BANK.A51 with Banking Mode 4.
EXTRN CODE (?B_SWITCH0)
CALL ?B_SWITCH0 ; init bank mechanism to code bank 0
#endif
;</h>
LJMP ?C_START
END
ADC.H
#ifndef __ADC_H__
#define __ADC_H__
#include "driver.h"
#define CHANNEL_02 02 //宏定义通道号
#define CHANNEL_03 03 //宏定义通道号
#define CHANNEL_06 06 //宏定义通道号
#define CHANNEL_07 07 //宏定义通道号
#define CHANNEL_13 13 //宏定义通道号
#define CHANNEL_14 14 //宏定义通道号
#define CHANNEL_15 15 //宏定义内部参考电源通道号
#define RREF 33000 //宏定义参考电阻大小
#define SAMPLED_WAIT_TIME 2 //采样等待时间 ms
#define ADC_SPEED 10 /* 0~15, ADC转换时间(CPU时钟数) = (n+1)*32 ADCCFG */
#define RES_FMT (1<<5) /* ADC结果格式 0: 左对齐, ADC_RES: D11 D10 D9 D8 D7 D6 D5 D4, ADC_RESL: D3 D2 D1 D0 0 0 0 0 */
/* ADCCFG 1: 右对齐, ADC_RES: 0 0 0 0 D11 D10 D9 D8, ADC_RESL: D7 D6 D5 D4 D3 D2 D1 D0 */
#define ADC_CH 7 /* 1~16, ADC转换通道数, 需同步修改 DMA_ADC_CHSW 转换通道 */
#define ADC_DMA_CH_CONVERSION_NUM 16 //单通道采样次数
#define ADC_DMA_ABANDON_NUM 4 //采样数据舍去最低和最高位数
#define ADC_DATA 18 /* 6~n, 每个通道ADC转换数据总数, 转换次数+2, 需同步修改 DMA_ADC_CFG2 转换次数 */ //转换10次
#define DMA_ADDR 0x1400 /* DMA数据存放地址 */
//#define MAGNIFICATION 50 //检测电路放大倍数宏定义
//#define ADC_TEMP_NUM 20 //ADC数据暂存数据数量
//#define ADC_DATA_ABANDON_NUM 4 //ADC实时平均值去掉首位数
//#define ADC_DATA_OVERFLOW 20 //连续溢出次数
typedef struct adc_init{
unsigned char channel; //通道选择 占用四个字节 0~15代表16个通道 15是内部参考电压通道
unsigned char resfmt; //数据对其方式 占用一个字节 0为左对齐 1为右对齐
unsigned char speed; //ADC时钟配置 占用4个字节 0~15 代表1~16分频
unsigned char cssetup; //通道选择时间,即准备时间 占用一个字节 0: 1ADC个时钟 1:2ADC个时钟
unsigned char smpduty; //采样时间 占用5个字节 0~31 代表1~32个ADC时钟
unsigned char cshold; //保持时间 占用2个字节 0~3 代表 1~4个ADC时钟
unsigned char cvtimesel; //自动转换次数 占用三个字节 3~7 代表1/2/4/8/16此
}USER_ADC_INIT;
typedef struct adc{
// unsigned short adc_buff[20]; //缓存ADC采集的数据
unsigned char adc_daq_num; //ADC数据采集次数
unsigned char adc_daq_cnt; //ADC数据采样计数
unsigned char adc_sampling_ok; //采样完成标志位
unsigned char adc_remove_ht_num; //adc滤波使用,ADC采集一组数据,从小到达排序后滤除首尾偏移量数据的数量
unsigned long adc_sum; //adc累加和
unsigned short voltage_data; //用于存储电源电压的数据
unsigned short adc_results; //ADC最终计算结果
}ADC_DATA_PROCESSING;
extern unsigned short xdata dma_buffer[ADC_CH][ADC_DATA];
extern unsigned short sampled_wait_time_count; //采样间隔时间计数
extern ADC_DATA_PROCESSING ADC_CHANNEL_02;
extern ADC_DATA_PROCESSING ADC_CHANNEL_03;
extern ADC_DATA_PROCESSING ADC_CHANNEL_06;
extern ADC_DATA_PROCESSING ADC_CHANNEL_07;
extern ADC_DATA_PROCESSING ADC_CHANNEL_13;
extern ADC_DATA_PROCESSING ADC_CHANNEL_14;
extern unsigned char dma_adc_ok; //dma_adc采样完成标志位
void ADC_KC(unsigned char adc_in_type); //切换通道函数
void user_adc_init_service();
void adc_service(unsigned char *adc_sampling_ok);
void adc_1ms();
#endif
ADC.C
#include "adc.h"
#include <string.h> // 必须包含memset头文件
#include <intrins.h>
#include "b3950_10k.h"
unsigned char user_channel_num = 0; // 用户通道编号
unsigned char test_flag = 0; //测试头文件
ADC_DATA_PROCESSING ADC_CHANNEL_15 = {0};
ADC_DATA_PROCESSING ADC_CHANNEL_02 = {0};
ADC_DATA_PROCESSING ADC_CHANNEL_03 = {0};
ADC_DATA_PROCESSING ADC_CHANNEL_06 = {0};
ADC_DATA_PROCESSING ADC_CHANNEL_07 = {0};
ADC_DATA_PROCESSING ADC_CHANNEL_13 = {0};
ADC_DATA_PROCESSING ADC_CHANNEL_14 = {0};
unsigned short xdata dma_buffer[ADC_CH][ADC_DATA] _at_ DMA_ADDR;
//unsigned short dma_buffer[ADC_CH][ADC_DATA] = {0};
unsigned char dma_adc_ok = 0; //dma_adc采样完成标志位
unsigned short adc_vref = 0; //内部参考电压MV
/***********************************************************/
// description: 用户ADC初始化函数
//* param {*}
//* return {*}
/***********************************************************/
void adc_star()
{
ADC_CONTR |= (0x01 << 6); //启动转化
}
/***********************************************************/
// description: 用户ADC切换通道
//* param {*}
//* return {*} 0~15代表通道0~15
/***********************************************************/
void adc_change_channel(unsigned char channel_id)
{
unsigned char temp_uchar_data = 0;
temp_uchar_data = ADC_CONTR;
temp_uchar_data &= 0xF0; //先清零通道选择位
temp_uchar_data |= channel_id; //赋值通道选择位
ADC_CONTR = temp_uchar_data; //赋值寄存器
}
/***********************************************************/
// description:void adc_gpio_init()
//* param {*}
//* return {*}
/***********************************************************/
void adc_gpio_init()
{
P5M0 &= ~(0x01 << 4);
P5M1 |= (0x01 << 4); //p5.4接收管脚高阻输入
P1M0 &= ~(0x01 << 3);
P1M1 |= (0x01 << 3); //p1.3接收管脚高阻输入
P1M0 &= ~(0x01 << 7);
P1M1 |= (0x01 << 7); //p1.7接收管脚高阻输入
P1M0 &= ~(0x01 << 6);
P1M1 |= (0x01 << 6); //p1.6接收管脚高阻输入
P0M0 &= ~(0x01 << 6);
P0M1 |= (0x01 << 6); //p0.6接收管脚高阻输入
P0M0 &= ~(0x01 << 5);
P0M1 |= (0x01 << 5); //p0.5接收管脚高阻输入
P5M0 |= (0x01 << 3);
P5M1 &= ~(0x01 << 3); //p5.3为发送管脚推挽输出
P0M0 |= (0x01 << 7);
P0M1 &= ~(0x01 << 7); //p0.7为发送管脚推挽输出
P1M0 |= (0x01 << 4);
P1M1 &= ~(0x01 << 4); //p1.4为发送管脚推挽输出
P1M0 |= (0x01 << 5);
P1M1 &= ~(0x01 << 5); //p1.5为发送管脚推挽输出
CHANNEL01_RWT_CONTROL_GPIO = 0;
CHANNEL01_SWT_CONTROL_GPIO = 0;
CHANNEL02_RWT_CONTROL_GPIO = 0;
CHANNEL02_SWT_CONTROL_GPIO = 0; //初始化关闭检测通道
}
/***********************************************************/
// description: ADC初始化库
//* param {*}
//* return {*}
/***********************************************************/
void s_adc_init(USER_ADC_INIT *adc)
{
ADC_CONTR |= 0x80; //开启ADC电源
ADC_CONTR &= 0xF0; //先清零到通道一全为0
ADC_CONTR |= (adc -> channel); //通道选择 占用四个字节 0~15代表16个通道 15是内部参考电压通道
ADCCFG = 0; //先清零此寄存器
ADCCFG |= (adc -> resfmt << 5); //设置数据对其方式寄存器
ADCCFG |= (adc -> speed); //设置ADC时钟分频寄存器
ADCTIM = 0;
ADCTIM |= (adc -> cssetup << 7); //设置通道选择时间寄存器
ADCTIM |= (adc -> smpduty); //设置采样时间寄存器
ADCTIM |= (adc -> cshold << 5); //设置保持时间寄存器
ADCEXCFG = 0;
ADCEXCFG |= (adc -> cvtimesel); //设置自动转换次数寄存器
}
/***********************************************************/
// description: adc_dma_star启动
//* param {*}
//* return {*} rx_buff_add:接收数据的地址
/***********************************************************/
void adc_dma_star()
{
// ADC_CONTR |= (0x01 << 6); //启动转化
DMA_ADC_CR |= (0x01 << 6); //启动DMA_ADC功能
}
/***********************************************************/
// description: ADC_DMA初始化库
//* param {*}
//* return {*} rx_buff_add:接收数据的地址
/***********************************************************/
void s_adc_dma_init(unsigned short rx_buff_add)
{
DMA_ADC_STA = 0x00;
// DMA_ADC_CFG |= (0x02 << 2); //调高中断优先级
DMA_ADC_RXAH = (unsigned char)(rx_buff_add >> 8);
DMA_ADC_RXAL = (unsigned char)rx_buff_add;
DMA_ADC_CFG2 = 11; //每个通道ADC转换次数:16次
DMA_ADC_CHSW0 = 0; //ADC通道使能寄存器 ADC7~ADC0
DMA_ADC_CHSW1 = 0; //ADC通道使能寄存器 ADC15~ADC8
DMA_ADC_CHSW0 |= (0x01 << 2); //ADC通道使能寄存器 ADC7~ADC0 //开启02通道
DMA_ADC_CHSW0 |= (0x01 << 3); //ADC通道使能寄存器 ADC15~ADC8 //开启03通道
DMA_ADC_CHSW0 |= (0x01 << 6); //ADC通道使能寄存器 ADC7~ADC0 //开启06通道
DMA_ADC_CHSW0 |= (0x01 << 7); //ADC通道使能寄存器 ADC15~ADC8 //开启07通道
DMA_ADC_CHSW1 |= (0x01 << 5); //ADC通道使能寄存器 ADC7~ADC0 //开启13通道
DMA_ADC_CHSW1 |= (0x01 << 6); //ADC通道使能寄存器 ADC15~ADC8 //开启14通道
DMA_ADC_CHSW1 |= (0x01 << 7); //ADC通道使能寄存器 ADC15~ADC8 //开启15通道
DMA_ADC_CR |= (0x01 << 7); //使能ADC_DMA功能
DMA_ADC_CFG |= (0x01 << 7); //使能中断
}
/***********************************************************/
// description: 用户ADC初始化函数
//* param {*}
//* return {*} 主函数中调用
/***********************************************************/
void user_adc_init() //ADC转换速度为 62.836 KSPS
{
USER_ADC_INIT adc_init_data = {0};
user_channel_num = 2; //初始化为15通道,先检测外部供电电压
adc_init_data.channel = user_channel_num; //通道选择 占用四个字节 0~15代表16个通道 15是内部参考电压通道
adc_init_data.resfmt = 1; //数据对其方式 占用一个字节 0为左对齐 1为右对齐
adc_init_data.speed = ADC_SPEED; //ADC时钟配置 占用4个字节 0~15 代表1~16分频
adc_init_data.cssetup = 0; //通道选择时间,即准备时间 占用一个字节 0: 1ADC个时钟 1:2ADC个时钟
adc_init_data.smpduty = 15; //采样时间 占用5个字节 0~31 代表1~32个ADC时钟
adc_init_data.cshold = 2; //保持时间 占用2个字节 0~3 代表 1~4个ADC时钟
adc_init_data.cvtimesel = 7; //自动转换次数 占用三个字节 3~7 代表1/2/4/8/16此 转换一次
s_adc_init(&adc_init_data); //初始化ADC设置数据
}
/***********************************************************/
// description: 用户ADC数据处理函数初始化
//* param {*}
//* return {*} 主函数中调用 sampling_num:采样数量 filter_count:滤波数量
/***********************************************************/
void user_adc_data_processing(ADC_DATA_PROCESSING *user_adc_data, unsigned char sampling_num, unsigned char filter_count)
{
memset(user_adc_data, 0, sizeof(ADC_DATA_PROCESSING));
user_adc_data -> adc_daq_num = sampling_num;
user_adc_data -> adc_daq_cnt = 0;
user_adc_data -> adc_sampling_ok = 0;
user_adc_data -> adc_remove_ht_num = filter_count;
user_adc_data -> adc_sum = 0;
user_adc_data -> voltage_data = 0;
user_adc_data -> adc_results = 0;
}
/***********************************************************/
// description: 用户ADC初始服务函数
//* param {*}
//* return {*} 主函数中调用
/***********************************************************/
void user_adc_init_service()
{
adc_gpio_init();
adc_vref = CHIPID7;
adc_vref <<= 8;
adc_vref += CHIPID8; //读取内部参考电压
user_adc_data_processing(&ADC_CHANNEL_15,local_gateway_data -> user_adc_configuration.sample_count,local_gateway_data -> user_adc_configuration.filter_count);
user_adc_data_processing(&ADC_CHANNEL_02,local_gateway_data -> user_adc_configuration.sample_count,local_gateway_data -> user_adc_configuration.filter_count);
user_adc_data_processing(&ADC_CHANNEL_03,local_gateway_data -> user_adc_configuration.sample_count,local_gateway_data -> user_adc_configuration.filter_count);
user_adc_data_processing(&ADC_CHANNEL_06,local_gateway_data -> user_adc_configuration.sample_count,local_gateway_data -> user_adc_configuration.filter_count);
user_adc_data_processing(&ADC_CHANNEL_07,local_gateway_data -> user_adc_configuration.sample_count,local_gateway_data -> user_adc_configuration.filter_count);
user_adc_data_processing(&ADC_CHANNEL_13,local_gateway_data -> user_adc_configuration.sample_count,local_gateway_data -> user_adc_configuration.filter_count);
user_adc_data_processing(&ADC_CHANNEL_14,local_gateway_data -> user_adc_configuration.sample_count,local_gateway_data -> user_adc_configuration.filter_count);
user_adc_init(); //初始化ADC
s_adc_dma_init((unsigned short)DMA_ADDR); //adc_dma初始化
// s_adc_dma_init((unsigned short)&dma_buffer[0][0]); //adc_dma初始化
sampled_wait_time_count = local_gateway_data -> user_adc_configuration.sampling_period; //赋值新的采样周期
}
/***********************************************************/
// description: void ADC_Isr() interrupt 5
//* param {*}
//* return {*} ADC中断函数
/***********************************************************/
/*
void ADC_Isr() interrupt 5
{
unsigned short temp_ushort_data = 0;
ADC_CONTR &= ~0x20; //清除中断标志位
if(user_channel_num == channel_15)
{
temp_ushort_data = ADC_RES;
temp_ushort_data <<= 8;
temp_ushort_data += ADC_RESL;
temp_ushort_data >>= 4; // 解析实际数据
ADC_CHANNEL_15.adc_buff[ADC_CHANNEL_15.adc_daq_cnt++] = temp_ushort_data;
user_channel_num = CHANNEL_10;
ADC_KC(user_channel_num);
}
else if(user_channel_num == CHANNEL_10)
{
temp_ushort_data = ADC_RES;
temp_ushort_data <<= 8;
temp_ushort_data += ADC_RESL;
temp_ushort_data >>= 4; // 解析实际数据
ADC_CHANNEL_10.adc_buff[ADC_CHANNEL_10.adc_daq_cnt++] = temp_ushort_data;
user_channel_num = CHANNEL_11;
ADC_KC(user_channel_num);
}
else if(user_channel_num == CHANNEL_11)
{
temp_ushort_data = ADC_RES;
temp_ushort_data <<= 8;
temp_ushort_data += ADC_RESL;
temp_ushort_data >>= 4; // 解析实际数据
ADC_CHANNEL_11.adc_buff[ADC_CHANNEL_11.adc_daq_cnt++] = temp_ushort_data;
sampled_wait_time_count = SAMPLED_WAIT_TIME;
if(ADC_CHANNEL_11.adc_daq_cnt >= ADC_CHANNEL_11.adc_daq_num)
{
sampled_wait_time_count = 0;
ADC_CHANNEL_11.adc_sampling_ok = 1; //采样完成置位
// temper_read_flag = 0; //清零温度读取数据头文件
}
}
}
*/
/***********************************************************/
// description: void ADC_dmaIsr() interrupt 13
//* param {*}
//* return {*} ADC中断函数
/***********************************************************/
void ADC_DMA_Interrupt(void) interrupt 13
{
if(DMA_ADC_STA & 0x01) //如果中断响应为DMA_adc中断
{
// ADC_CONTR &= ~(0x01 << 6); //禁用转化
DMA_ADC_CR &= ~(0x01 << 6); //禁用DMA_ADC功能
DMA_ADC_CR &= ~(0x01 << 7); //禁用ADC_DMA功能
DMA_ADC_STA = 0;
CHANNEL01_RWT_CONTROL_GPIO = 0;
CHANNEL01_SWT_CONTROL_GPIO = 0;
CHANNEL02_RWT_CONTROL_GPIO = 0;
CHANNEL02_SWT_CONTROL_GPIO = 0; //初始化关闭检测通道
dma_adc_ok = 1; //采样完成
}
}
/***********************************************************/
// description: adc_int() adc_start检测
//* param {*}
//* return {*}
/***********************************************************/
/*
void ADC_KC(unsigned char adc_in_type)
{
switch(adc_in_type)
{
case CHANNEL_10:
adc_change_channel(CHANNEL_10);
adc_star();
break;
case CHANNEL_11:
adc_change_channel(CHANNEL_11);
adc_star();
break;
case CHANNEL_15:
adc_change_channel(CHANNEL_15);
adc_star();
break;
}
}
*/
/***********************************************************/
// description: power_voltage_count() 电源电压计算
//* param {*}
//* return {*} 内部函数调用
/***********************************************************/
unsigned short power_voltage_count(unsigned short power_adc_data)
{
unsigned long temp_ulong_data = 0;
temp_ulong_data = (unsigned long)adc_vref * 4096 / power_adc_data;
return (unsigned short)temp_ulong_data;
}
/***********************************************************/
// description: adc_voltage_count() adc电压计算
//* param {*}
//* return {*} 内部函数调用
/***********************************************************/
unsigned short adc_voltage_count(unsigned short power_voltage, unsigned short adc_data, unsigned short adc_calibration_coefficient)
{
unsigned long temp_ulong_data = 0;
temp_ulong_data = (unsigned long)adc_data * power_voltage / 4096;
temp_ulong_data = temp_ulong_data * adc_calibration_coefficient / 1000;
return (unsigned short)temp_ulong_data;
}
/***********************************************************/
// description: adc_data_conversion_function
//* param {*}
//* return {*} ADC数据转换函数
/***********************************************************/
void adc_data_conversion_function(ADC_DATA_PROCESSING *user_adc_data, unsigned short p[][ADC_DATA], unsigned char data_id)
{
unsigned short i,j,k;
unsigned short temp_ushort_data = 0;
if(dma_adc_ok == 1)
{
user_adc_data -> adc_sum = 0;
/**************************************ADC0通道参考电压采集采集数据滤波*********************************/
/*******************排序******************/
for(i = 0;i < (user_adc_data -> adc_daq_num - 1); i++)
{
for(j = 0;j < (user_adc_data -> adc_daq_num - i - 1); j++)
{
if(p[data_id][j] > p[data_id][j + 1])
{
temp_ushort_data = p[data_id][j];
p[data_id][j] = p[data_id][j + 1];
p[data_id][j + 1] = temp_ushort_data;
}
}
}
/***************去掉最大值最小值求平均*****************/
for(k = user_adc_data -> adc_remove_ht_num; k < (user_adc_data -> adc_daq_num - user_adc_data -> adc_remove_ht_num); k++)
{
user_adc_data -> adc_sum = user_adc_data -> adc_sum + p[data_id][k];
}
user_adc_data -> adc_results = (unsigned short)((user_adc_data -> adc_sum) / (user_adc_data -> adc_daq_num - (user_adc_data -> adc_remove_ht_num * 2)));
}
}
/***********************************************************/
// description: adc_service()
//* param {*}
//* return {*} ADC服务函数
/***********************************************************/
unsigned short temper_buff[50] = {0}; //温度数据暂存函数
void adc_service(unsigned char *adc_sampling_ok)
{
// unsigned short temper_buff[50] = {0}; //温度数据暂存函数
unsigned short sys_power_voltage = 0;
static unsigned char temper01_machion = 0;
static unsigned char temper02_machion = 0;
static unsigned char temper03_machion = 0;
static unsigned char temper04_machion = 0; //温度状态机
if(*adc_sampling_ok == 1)
{
adc_data_conversion_function(&ADC_CHANNEL_02,dma_buffer, 0);
adc_data_conversion_function(&ADC_CHANNEL_03,dma_buffer, 1);
adc_data_conversion_function(&ADC_CHANNEL_06,dma_buffer, 2);
adc_data_conversion_function(&ADC_CHANNEL_07,dma_buffer, 3);
adc_data_conversion_function(&ADC_CHANNEL_13,dma_buffer, 4);
adc_data_conversion_function(&ADC_CHANNEL_14,dma_buffer, 5);
adc_data_conversion_function(&ADC_CHANNEL_15, dma_buffer, 6);
sys_power_voltage = power_voltage_count(ADC_CHANNEL_15.adc_results);
ADC_CHANNEL_02.voltage_data = adc_voltage_count(sys_power_voltage, ADC_CHANNEL_02.adc_results, local_gateway_data -> user_vol_calibration.coefficient[0]);
ADC_CHANNEL_03.voltage_data = adc_voltage_count(sys_power_voltage, ADC_CHANNEL_03.adc_results, local_gateway_data -> user_vol_calibration.coefficient[1]);
ADC_CHANNEL_06.voltage_data = adc_voltage_count(sys_power_voltage, ADC_CHANNEL_06.adc_results, local_gateway_data -> user_ntc_vol_calibration.coefficient[2]);
modbus_reg[171] = ADC_CHANNEL_06.voltage_data;
ADC_CHANNEL_07.voltage_data = adc_voltage_count(sys_power_voltage, ADC_CHANNEL_07.adc_results, local_gateway_data -> user_ntc_vol_calibration.coefficient[3]);
modbus_reg[172] = ADC_CHANNEL_07.voltage_data;
ADC_CHANNEL_13.voltage_data = adc_voltage_count(sys_power_voltage, ADC_CHANNEL_13.adc_results, local_gateway_data -> user_ntc_vol_calibration.coefficient[0]);
modbus_reg[169] = ADC_CHANNEL_13.voltage_data;
ADC_CHANNEL_14.voltage_data = adc_voltage_count(sys_power_voltage, ADC_CHANNEL_14.adc_results, local_gateway_data -> user_ntc_vol_calibration.coefficient[1]);
modbus_reg[170] = ADC_CHANNEL_14.voltage_data;
/************************放入NTC电阻转换函数**********************/
if(user_temper01_rwt_res.temper_read_cnt < user_temper01_rwt_res.temper_read_num)
{
user_temper01_rwt_res.temper_read_cnt++;
if(user_temper01_rwt_res.temper_read_cnt == user_temper01_rwt_res.temper_read_num)
{
temper01_machion = 1;
user_temper01_rwt_res.temper_read_cnt = 0;
}
}
user_temper01_rwt_res.adc_buff[user_temper01_rwt_res.temper_read_cnt] = temper_res_count(sys_power_voltage, ADC_CHANNEL_13.voltage_data, RREF);
if(temper01_machion == 1)
{
/***********************补充温度数据滤波及查表函数*************************/
memcpy(temper_buff, user_temper01_rwt_res.adc_buff, ((user_temper01_rwt_res.temper_read_num) * 2)); //先将数据赋值到缓存数组
temper_res_data_filtering(&user_temper01_rwt_res, temper_buff); //对缓存数组进型排序和滤波并求出平均值
temper_check_table(ntc_res_data, TEMPER_TABLE_STAR_NUM, TEMPER_TABLE_STOP_NUM, (unsigned short)(user_temper01_rwt_res.temper_data_sum),
(unsigned short *)&(local_gateway_data -> user_temper_sampling_data.temper[0])); //查表得出温度数据
/***********************计算校准后数据*************************/
}
if(user_temper01_swt_res.temper_read_cnt < user_temper01_swt_res.temper_read_num)
{
user_temper01_swt_res.temper_read_cnt++;
if(user_temper01_swt_res.temper_read_cnt == user_temper01_swt_res.temper_read_num)
{
temper02_machion = 1;
user_temper01_swt_res.temper_read_cnt = 0;
}
}
user_temper01_swt_res.adc_buff[user_temper01_swt_res.temper_read_cnt] = temper_res_count(sys_power_voltage, ADC_CHANNEL_14.voltage_data, RREF);
if(temper02_machion == 1)
{
/***********************补充温度数据滤波及查表函数*************************/
memcpy(temper_buff, user_temper01_swt_res.adc_buff, ((user_temper01_swt_res.temper_read_num) * 2));
temper_res_data_filtering(&user_temper01_swt_res, temper_buff);
temper_check_table(ntc_res_data, TEMPER_TABLE_STAR_NUM, TEMPER_TABLE_STOP_NUM, (unsigned short)(user_temper01_swt_res.temper_data_sum),
(unsigned short *)&(local_gateway_data -> user_temper_sampling_data.temper[1])); //查表得出温度数据
}
if(user_temper02_rwt_res.temper_read_cnt < user_temper02_rwt_res.temper_read_num)
{
user_temper02_rwt_res.temper_read_cnt++;
if(user_temper02_rwt_res.temper_read_cnt == user_temper02_rwt_res.temper_read_num)
{
temper03_machion = 1;
user_temper02_rwt_res.temper_read_cnt = 0;
}
}
user_temper02_rwt_res.adc_buff[user_temper02_rwt_res.temper_read_cnt] = temper_res_count(sys_power_voltage, ADC_CHANNEL_06.voltage_data, RREF);
if(temper03_machion == 1)
{
/***********************补充温度数据滤波及查表函数*************************/
memcpy(temper_buff, user_temper02_rwt_res.adc_buff, ((user_temper02_rwt_res.temper_read_num) * 2));
temper_res_data_filtering(&user_temper02_rwt_res, temper_buff);
temper_check_table(ntc_res_data, TEMPER_TABLE_STAR_NUM, TEMPER_TABLE_STOP_NUM, (unsigned short)(user_temper02_rwt_res.temper_data_sum),
(unsigned short *)&(local_gateway_data -> user_temper_sampling_data.temper[2])); //查表得出温度数据
}
if(user_temper02_swt_res.temper_read_cnt < user_temper02_swt_res.temper_read_num)
{
user_temper02_swt_res.temper_read_cnt++;
if(user_temper02_swt_res.temper_read_cnt == user_temper02_swt_res.temper_read_num)
{
temper04_machion = 1;
user_temper02_swt_res.temper_read_cnt = 0;
}
}
user_temper02_swt_res.adc_buff[user_temper02_swt_res.temper_read_cnt] = temper_res_count(sys_power_voltage, ADC_CHANNEL_07.voltage_data, RREF);
if(temper04_machion == 1)
{
/***********************补充温度数据滤波及查表函数*************************/
memcpy(temper_buff, user_temper02_swt_res.adc_buff, ((user_temper02_swt_res.temper_read_num) * 2));
temper_res_data_filtering(&user_temper02_swt_res, temper_buff);
temper_check_table(ntc_res_data, TEMPER_TABLE_STAR_NUM, TEMPER_TABLE_STOP_NUM, (unsigned short)(user_temper02_swt_res.temper_data_sum),
(unsigned short *)&(local_gateway_data -> user_temper_sampling_data.temper[3])); //查表得出温度数据
}
/***********************放入DAC输出电压反馈采集转换函数************/
local_gateway_data -> user_dac_output_vol.value[0] = dac_output_vol_conversion(ADC_CHANNEL_02.voltage_data, TOTAL_RES, PULL_DOWN_RES);
local_gateway_data -> user_dac_output_vol.value[1] = dac_output_vol_conversion(ADC_CHANNEL_03.voltage_data, TOTAL_RES, PULL_DOWN_RES);
/***********************放入DAC输出电压反馈PID计算函数************/
sampled_wait_time_count = local_gateway_data -> user_adc_configuration.sampling_period; //赋值新的采样周期
*adc_sampling_ok = 0;
}
}
/***********************************************************/
// description: void adc_1ms()
//* param {*}
//* return {*} adc 1ms中断函数 open_flag: 开启计时标志位 或读取传感器数据标志位
/***********************************************************/
unsigned short sampled_wait_time_count = 0; //采样间隔时间计数
void adc_1ms()
{
if(sampled_wait_time_count > 0)
{
sampled_wait_time_count--;
if(sampled_wait_time_count == 0)
{
DMA_ADC_CR |= 0x01 << 7; //先使能ADC_DMA功能
CHANNEL01_RWT_CONTROL_GPIO = 1;
CHANNEL01_SWT_CONTROL_GPIO = 1;
CHANNEL02_RWT_CONTROL_GPIO = 1;
CHANNEL02_SWT_CONTROL_GPIO = 1; //拉低检测下管开启检测
_nop_();
_nop_();
_nop_();
_nop_();
_nop_(); //延时使拉低过程稳定下来
adc_dma_star(); //触发DMA
}
}
}
|
|