/****************************************************************************** 版权所有: 文件名称: adc.c 文件版本: 01.01 创建作者: sunxi 创建日期: 2025-06-09 功能说明: adc驱动程序。 其它说明: 修改记录: */ /*------------------------------ 头文件 --------------------------------------- */ #include "bsp.h" #include "rt.h" #include "head.h" #include #include "rt_printf.h" #include "shm_comm_packet.h" #include /*------------------------------ 宏定义 --------------------------------------- */ #if CFG_BSP_DEBUG #define _ADC_DEBUG #endif #define AC_HZ_NORMAL 50.0 // 交流标准频率 #define ADC_DOT_BUF_SIZE ((CFG_ADC_CHANNEL)*(CFG_ADC_DOTS_PER_CHANNEL*2)*2) /*------------------------------ 全局变量 ------------------------------------- */ // AD片选地址,8、9、10、11槽对应CS2、CS1、CS3、CS4。 static int g_adc_slot2cs[EQU_SLOT_AC_NUM] = {0}; static u8 g_adc_chip; static u32 g_adc_range[EQU_SLOT_AC_NUM]; const u8 g_cs_channel_table[CFG_ADC_CHANNEL]={1,9,2,10,3,11,4,12,5,13,6,14,7,15,8,16}; //每个通道占用的空间:CFG_ADC_DOTS_PER_CHANNEL*2*2 = 128*2*2=512 //通道数:CFG_ADC_CHANNEL+2= 64+2=66 //总空间:512*18=9216=0x2400 //保证首地址是buf长度两倍的倍数。以利用MAC计算的MASK寄存器来达到 //循环buf的功能。注意每个通道buf的后半部分目前没有利用,以后可以用来干需要干的事情. //通道加2,用作开入开出等状态保存。 // 不能使用分配的DMA内存,因为冷火实时linux平台不能使用动态内存映射。 //short (*g_adc_dots)[CFG_ADC_DOTS_PER_CHANNEL*2]; //s16 (*g_adc_dots)[CFG_ADC_DOTS_PER_CHANNEL*2] = (short (*)[CFG_ADC_DOTS_PER_CHANNEL*2])0x8ff00000; s16 (*g_adc_dots)[CFG_ADC_DOTS_PER_CHANNEL*2]; struct timespec ts_adc_dots[CFG_ADC_DOTS_PER_CHANNEL];//时间戳 // 128点录波,32点计算 // 注意此buf由于是DMA类型,不能在实时中断中使用,只能在线程中使用。 //s16 g_adc_dots_rec[CFG_ADC_DOTS_PER_CHANNEL*4][CFG_ADC_CHANNEL]; s16 (*g_adc_dots_rec)[CFG_ADC_CHANNEL]; u32 g_adc_dots_rec_dma; // 直流量测量采样点BUF u16 g_adc_dots_dc[CFG_ADC_CHANNEL_DC][CFG_ADC_DOTS_PER_CHANNEL]; //ADC同步标志,表示ADC采样点BUFFER中的数据是否有效,AD7616转换的第一次数据也无效。 int g_adc_sync = -(CFG_ADC_DOTS_PER_CHANNEL+1); // ADC点BUF的索引,当前索引下无值。 volatile unsigned long g_adc_dots_count; int g_adc_channel; unsigned long g_adZero=14790; char g_adc_name[CFG_ADC_CHANNEL_ALL][20]; struct rt_stat g_stat_adc[CFG_ADC_CHANNEL_ALL]; // 跟踪频率 float g_freq = 50.0 ; // 直流量测量采样点BUF u16 g_adc_dots_dc[CFG_ADC_CHANNEL_DC][CFG_ADC_DOTS_PER_CHANNEL]; uint32_t g_yx_buf[2] = {0xffffffff,0xffffffff}; //预留64个遥信 int g_adc_stat_flag=0; volatile unsigned int adc_wp; volatile unsigned int adc_rp; bool prt_flag; volatile unsigned long g_adc_dots_data_count; SHM_VER_T LuoHe_version; /*------------------------------ 函数声明 ------------------------------------- */ void dido_di_poll(SHM_SAMPLE_T *sample_data); /*------------------------------ 外部函数 ------------------------------------- */ //设置各通道的参考电压 static int write_v_default(uint8_t no, uint8_t *data) { int ret = 0; int cnt = 0; if(data == NULL) return -1; while(1) { ret = shm_comm_packet_write(SHM_ADDR_D_RFV_1+(SHM_ADDR_D_RFV_2-SHM_ADDR_D_RFV_1)*no, data, sizeof(SHM_RFV_T)); if(ret > 0) { break; } if(++cnt > 3) break; usleep(30); } return ret; } int adc_set_v_default(int no, u32 value) { int ret = 0; SHM_RFV_T v; v.rc = value; ret = write_v_default(no,(uint8_t *)&v); return ret; } void adc_get_range_config(int no,int slot) { int i,scale,channel,shift; u32 rc; rc = 0; for(i=0;i 0) { return wp.write_flag_A; } if(++cnt > 3) break; usleep(30); } return ret; } static int get_adc_sample(int index, uint8_t *out_data) { SHM_SAMPLE_T sample; int ret = 0; int cnt = 0; if(out_data == NULL) return -1; while(1) { ret = shm_comm_packet_read_noABcrc(SHM_ADDR_U_ADC_1+index*(sizeof(sample)), sizeof(sample), out_data, sizeof(sample)); if(ret > 0) { break; } if(++cnt > 3) break; usleep(30); } return ret; } static int get_e907_version(SHM_VER_T* par) { SHM_VER_T ver; int ret = 0; int cnt = 0; if(par == NULL) return -1; while(1) { ret = shm_comm_packet_read(SHM_ADDR_U_VER, sizeof(ver), (uint8_t *)&ver, sizeof(ver)); if(ret > 0) { par->ver = ver.ver; par->v_crc = ver.v_crc; strcpy(par->time,ver.time); return 0; } if(++cnt > 3) break; usleep(30); } return -1; } int adc_init(void) { int ret = 0; int i; /* ret = get_adc_wp(); if(ret < 0) { rt_printf("get_adc_wp 返回错误值,ret=%d!\r\n",adc_wp); return -1; } adc_wp = adc_rp = ret; */ memset(&LuoHe_version,0,sizeof(LuoHe_version)); g_adc_dots_count=0; prt_flag=false; // 采样计算点BUF初始化 // 32;周波数 g_adc_dots = malloc(ADC_DOT_BUF_SIZE); if(g_adc_dots == NULL) { rt_printf("g_adc_dots 分配失败!\r\n"); return -1; } memset(g_adc_dots, 0x55, ADC_DOT_BUF_SIZE); g_adc_dots_data_count=0; // 录波点BUF初始化 // 32;周波数 g_adc_dots_rec = malloc(CFG_ADC_CHANNEL*2*ADC_REC_DOTS_CHANNEL); if(g_adc_dots_rec == NULL) { rt_printf("g_adc_dots_rec 分配失败!\r\n"); rt_free(g_adc_dots); g_adc_dots = NULL; return -1; } // 初始化统计变量 for(i=0; i=SHM_ADC_WR_NUM) { adc_wp=0; } if(adc_rp>=SHM_ADC_WR_NUM) { adc_rp=0; } while(adc_wp!=adc_rp) { opt=((g_adc_dots_data_count&(ADC_REC_SAMPLE_RATE-1))==0)?TRUE:FALSE; ret = get_adc_sample(adc_rp,(uint8_t *)&sample_data); if(ret < 0) { if(++cnt > 3) { rt_printf("get_adc_sample 返回错误值, ret=%d!\r\n",ret); break; } continue; } //保存yx值 g_yx_buf[0] = sample_data.yx_buf[0]; g_yx_buf[1] = sample_data.yx_buf[1]; if(!recv_init) { recv_init = 1; //开机时裸核还没有把遥信送上下,这里重新初始化plc_init dido_init_di(); plc_init(); } dido_di_poll(&sample_data); for(i=0; i=SHM_ADC_WR_NUM) adc_rp=0; } return 0; } /****************************************************************************** 函数名称: adc_slot_is_ok 函数版本: 01.01 创建作者: sunxi 创建日期: 2016-02-01 函数说明: 检查对应槽的ADC芯片是否安装或损坏。 参数说明: slot: 0~3;从g_ac_slot_begin开始 返回值: 成功返回0. 修改记录: */ int adc_slot_is_ok(int slot) { if((u32)slot >= EQU_SLOT_AC_NUM) { return 0; } if(g_adc_chip & (1<= CFG_ADC_DOTS_PER_PERIOD) { index = index - CFG_ADC_DOTS_PER_PERIOD; index &= (~0x1); p = (short *)&g_adc_dots[channel][index]; } else { index = CFG_ADC_DOTS_PER_CHANNEL-CFG_ADC_DOTS_PER_PERIOD+index; index &= (~0x1); for(i = 0;i < CFG_ADC_DOTS_PER_CHANNEL - index;i++) { sam_buf[channel][i] = g_adc_dots[channel][index+i]; } for(i = 0;i cnt) { avg = stat->sum/stat->cnt; } rt_printf("%-24s%ld\t%ld\t%ld\t%ld\t%-16ld%ld\r\n",stat->name,stat->min,stat->max,stat->max - stat->min,avg,stat->sum,stat->cnt); } return 0; } int adc_stat_reset(void) { int i; g_adc_stat_flag = 0; for(i=0; i 0) { break; } if(++cnt > 3) break; usleep(30); } return ret; } #endif float dc_get(unsigned int index) { u32 i,v; float f; v = 0; for(i=0;i