ad7616.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. /******************************************************************************
  2. 版权所有:
  3. 文件名称: adc.c
  4. 文件版本: 01.01
  5. 创建作者: sunxi
  6. 创建日期: 2025-06-09
  7. 功能说明: adc驱动程序。
  8. 其它说明:
  9. 修改记录:
  10. */
  11. /*------------------------------ 头文件 ---------------------------------------
  12. */
  13. #include "bsp.h"
  14. #include "rt.h"
  15. #include "head.h"
  16. #include <malloc.h>
  17. #include "rt_printf.h"
  18. #include "shm_comm_packet.h"
  19. #include <mb.h>
  20. /*------------------------------ 宏定义 ---------------------------------------
  21. */
  22. #if CFG_BSP_DEBUG
  23. #define _ADC_DEBUG
  24. #endif
  25. #define AC_HZ_NORMAL 50.0 // 交流标准频率
  26. #define ADC_DOT_BUF_SIZE ((CFG_ADC_CHANNEL)*(CFG_ADC_DOTS_PER_CHANNEL*2)*2)
  27. /*------------------------------ 全局变量 -------------------------------------
  28. */
  29. // AD片选地址,8、9、10、11槽对应CS2、CS1、CS3、CS4。
  30. static int g_adc_slot2cs[EQU_SLOT_AC_NUM] = {0};
  31. static u8 g_adc_chip;
  32. static u32 g_adc_range[EQU_SLOT_AC_NUM];
  33. 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};
  34. //每个通道占用的空间:CFG_ADC_DOTS_PER_CHANNEL*2*2 = 128*2*2=512
  35. //通道数:CFG_ADC_CHANNEL+2= 64+2=66
  36. //总空间:512*18=9216=0x2400
  37. //保证首地址是buf长度两倍的倍数。以利用MAC计算的MASK寄存器来达到
  38. //循环buf的功能。注意每个通道buf的后半部分目前没有利用,以后可以用来干需要干的事情.
  39. //通道加2,用作开入开出等状态保存。
  40. // 不能使用分配的DMA内存,因为冷火实时linux平台不能使用动态内存映射。
  41. //short (*g_adc_dots)[CFG_ADC_DOTS_PER_CHANNEL*2];
  42. //s16 (*g_adc_dots)[CFG_ADC_DOTS_PER_CHANNEL*2] = (short (*)[CFG_ADC_DOTS_PER_CHANNEL*2])0x8ff00000;
  43. s16 (*g_adc_dots)[CFG_ADC_DOTS_PER_CHANNEL*2];
  44. struct timespec ts_adc_dots[CFG_ADC_DOTS_PER_CHANNEL];//时间戳
  45. // 128点录波,32点计算
  46. // 注意此buf由于是DMA类型,不能在实时中断中使用,只能在线程中使用。
  47. //s16 g_adc_dots_rec[CFG_ADC_DOTS_PER_CHANNEL*4][CFG_ADC_CHANNEL];
  48. s16 (*g_adc_dots_rec)[CFG_ADC_CHANNEL];
  49. u32 g_adc_dots_rec_dma;
  50. // 直流量测量采样点BUF
  51. u16 g_adc_dots_dc[CFG_ADC_CHANNEL_DC][CFG_ADC_DOTS_PER_CHANNEL];
  52. //ADC同步标志,表示ADC采样点BUFFER中的数据是否有效,AD7616转换的第一次数据也无效。
  53. int g_adc_sync = -(CFG_ADC_DOTS_PER_CHANNEL+1);
  54. // ADC点BUF的索引,当前索引下无值。
  55. volatile unsigned long g_adc_dots_count;
  56. int g_adc_channel;
  57. unsigned long g_adZero=14790;
  58. char g_adc_name[CFG_ADC_CHANNEL_ALL][20];
  59. struct rt_stat g_stat_adc[CFG_ADC_CHANNEL_ALL];
  60. // 跟踪频率
  61. float g_freq = 50.0 ;
  62. // 直流量测量采样点BUF
  63. u16 g_adc_dots_dc[CFG_ADC_CHANNEL_DC][CFG_ADC_DOTS_PER_CHANNEL];
  64. uint32_t g_yx_buf[2] = {0xffffffff,0xffffffff}; //预留64个遥信
  65. int g_adc_stat_flag=0;
  66. volatile unsigned int adc_wp;
  67. volatile unsigned int adc_rp;
  68. bool prt_flag;
  69. volatile unsigned long g_adc_dots_data_count;
  70. SHM_VER_T LuoHe_version;
  71. /*------------------------------ 函数声明 -------------------------------------
  72. */
  73. void dido_di_poll(SHM_SAMPLE_T *sample_data);
  74. /*------------------------------ 外部函数 -------------------------------------
  75. */
  76. //设置各通道的参考电压
  77. static int write_v_default(uint8_t no, uint8_t *data)
  78. {
  79. int ret = 0;
  80. int cnt = 0;
  81. if(data == NULL)
  82. return -1;
  83. while(1)
  84. {
  85. 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));
  86. if(ret > 0)
  87. {
  88. break;
  89. }
  90. if(++cnt > 3)
  91. break;
  92. usleep(30);
  93. }
  94. return ret;
  95. }
  96. int adc_set_v_default(int no, u32 value)
  97. {
  98. int ret = 0;
  99. SHM_RFV_T v;
  100. v.rc = value;
  101. ret = write_v_default(no,(uint8_t *)&v);
  102. return ret;
  103. }
  104. void adc_get_range_config(int no,int slot)
  105. {
  106. int i,scale,channel,shift;
  107. u32 rc;
  108. rc = 0;
  109. for(i=0;i<EQU_SLOT_AC_CHN;i++)
  110. {
  111. channel = equ_get_ac_channel(slot,i)&0x0f;
  112. // 确定需要移位的数量
  113. // 双数是通道A,在低16位
  114. // 单数是通道B,在高16位
  115. shift = (channel/2)*2;
  116. if((channel&0x01))
  117. {
  118. shift += 16;
  119. }
  120. if(channel == AD7616_DC0_CHANNEL || channel == AD7616_DC1_CHANNEL)
  121. {
  122. rc |= 2<<shift;// 5V
  123. continue;
  124. }
  125. scale = equ_get_ac_scale(slot,i);
  126. switch(scale)
  127. {
  128. case EQU_SCALE_PT_DEFAULT:
  129. case EQU_SCALE_PT_120K:
  130. case EQU_SCALE_PT_172K:
  131. case EQU_SCALE_PT_204K:
  132. case EQU_SCALE_CT_10A_51:
  133. case EQU_SCALE_CT_10A_120:
  134. rc |= 1<<shift; // 2.5V
  135. break;
  136. case EQU_SCALE_PT_102K:
  137. case EQU_SCALE_PT_120K_604:
  138. case EQU_SCALE_PT_264V_3V53:
  139. case EQU_SCALE_CT_100A_3V53:
  140. case EQU_SCALE_CT_DEFAULT:
  141. case EQU_SCALE_CT_10A_249:
  142. case EQU_SCALE_CT_10A_604:
  143. case EQU_SCALE_EVT_3V25_100V:
  144. case EQU_SCALE_PT_400V_3V53:
  145. case EQU_SCALE_CT_20A_3V53:
  146. rc |= 2<<shift;// 5V
  147. break;
  148. case EQU_SCALE_EVT_6V50_100V:
  149. case EQU_SCALE_ECT_1V_1A:
  150. case EQU_SCALE_ECT_0V2_1A: // 零序电子CT采用2.5V的范围
  151. rc |= 3<<shift; // 10V
  152. break;
  153. }
  154. }
  155. adc_set_v_default(no,rc);
  156. mb_notice_RfV_update(0);
  157. }
  158. static int get_adc_wp(void)
  159. {
  160. WP_T wp;
  161. int ret = 0;
  162. int cnt = 0;
  163. while(1)
  164. {
  165. ret = shm_comm_packet_read(SHM_ADDR_U_WP, sizeof(wp), (uint8_t *)&wp, sizeof(wp));
  166. if(ret > 0)
  167. {
  168. return wp.write_flag_A;
  169. }
  170. if(++cnt > 3)
  171. break;
  172. usleep(30);
  173. }
  174. return ret;
  175. }
  176. static int get_adc_sample(uint32_t addr, int index, uint8_t *out_data)
  177. {
  178. SHM_SAMPLE_T sample;
  179. int ret = 0;
  180. int cnt = 0;
  181. if(out_data == NULL)
  182. return -1;
  183. while(1)
  184. {
  185. ret = shm_comm_packet_read_noABcrc(addr + index*(sizeof(sample)), sizeof(sample), out_data, sizeof(sample));
  186. if(ret > 0)
  187. {
  188. break;
  189. }
  190. if(++cnt > 3)
  191. break;
  192. usleep(30);
  193. }
  194. return ret;
  195. }
  196. static int get_e907_version(SHM_VER_T* par)
  197. {
  198. SHM_VER_T ver;
  199. int ret = 0;
  200. int cnt = 0;
  201. if(par == NULL)
  202. return -1;
  203. while(1)
  204. {
  205. ret = shm_comm_packet_read(SHM_ADDR_U_VER, sizeof(ver), (uint8_t *)&ver, sizeof(ver));
  206. if(ret > 0)
  207. {
  208. par->ver = ver.ver;
  209. par->v_crc = ver.v_crc;
  210. strcpy(par->time,ver.time);
  211. return 0;
  212. }
  213. if(++cnt > 3)
  214. break;
  215. usleep(30);
  216. }
  217. return -1;
  218. }
  219. int adc_init(void)
  220. {
  221. int ret = 0;
  222. int i;
  223. /*
  224. ret = get_adc_wp();
  225. if(ret < 0)
  226. {
  227. rt_printf("get_adc_wp 返回错误值,ret=%d!\r\n",adc_wp);
  228. return -1;
  229. }
  230. adc_wp = adc_rp = ret;
  231. */
  232. memset(&LuoHe_version,0,sizeof(LuoHe_version));
  233. g_adc_dots_count=0;
  234. prt_flag=false;
  235. // 采样计算点BUF初始化
  236. // 32;周波数
  237. g_adc_dots = malloc(ADC_DOT_BUF_SIZE);
  238. if(g_adc_dots == NULL)
  239. {
  240. rt_printf("g_adc_dots 分配失败!\r\n");
  241. return -1;
  242. }
  243. memset(g_adc_dots, 0x55, ADC_DOT_BUF_SIZE);
  244. g_adc_dots_data_count=0;
  245. // 录波点BUF初始化
  246. // 32;周波数
  247. g_adc_dots_rec = malloc(CFG_ADC_CHANNEL*2*ADC_REC_DOTS_CHANNEL);
  248. if(g_adc_dots_rec == NULL)
  249. {
  250. rt_printf("g_adc_dots_rec 分配失败!\r\n");
  251. rt_free(g_adc_dots);
  252. g_adc_dots = NULL;
  253. return -1;
  254. }
  255. // 初始化统计变量
  256. for(i=0; i<CFG_ADC_CHANNEL_ALL; i++)
  257. {
  258. sprintf(g_adc_name[i],"adc%02d[%08lx]",i,(u32)g_adc_dots + i*sizeof(g_adc_dots[0]));
  259. rt_stat_init(&g_stat_adc[i],g_adc_name[i]);
  260. }
  261. for(i=0; i<EQU_SLOT_AC_NUM; i++) //配置通道的采样参数
  262. {
  263. adc_get_range_config(i,g_ac_slot_begin+g_adc_slot2cs[i]);
  264. }
  265. #if 0
  266. // 检查和槽对应的ADC芯片是否安装或损坏
  267. // printk("g_adc_chip=%02x.\r\n",g_adc_chip);
  268. for(i=0; i< EQU_SLOT_AC_NUM; i++)
  269. {
  270. if(equ_get_ac_num(g_ac_slot_begin+i))
  271. {
  272. if(adc_slot_is_ok(i) == 0)
  273. {
  274. rt_err_set(ERR_CODE_INIT_ADC,i);
  275. rt_printf("槽%02ld:ADC 芯片未安装或错误!\r\n",g_ac_slot_begin+i);
  276. }
  277. }
  278. }
  279. #endif
  280. return ret;
  281. }
  282. int adc_exit(void)
  283. {
  284. int ret=0;
  285. if(g_adc_dots_rec)
  286. {
  287. free(g_adc_dots_rec);
  288. g_adc_dots_rec=0;
  289. }
  290. if(g_adc_dots)
  291. {
  292. free(g_adc_dots);
  293. g_adc_dots=0;
  294. }
  295. return ret;
  296. }
  297. int adc_isr(int mod)
  298. {
  299. int opt,i;
  300. SHM_SAMPLE_T sample_data[2];
  301. int ret = 0;
  302. int cnt = 0;
  303. int index = 0;
  304. static int start_flag = 0;
  305. static int recv_init = 0;
  306. static int get_version_flag = 0;
  307. ret = get_adc_wp();
  308. if(ret < 0)
  309. {
  310. // rt_printf("get_adc_wp 返回错误值, ret=%d!\r\n",ret);
  311. return -1;
  312. }
  313. if(get_version_flag == 0)
  314. {
  315. ret = get_e907_version(&LuoHe_version);
  316. if(ret == 0)
  317. {
  318. get_version_flag = 1;//noted by sunxi:这个应该要读成功后,才置为1.
  319. rt_printf("裸核版本号: ver=v%d.%02d,%s,crc=%X\r\n",LuoHe_version.ver/100,LuoHe_version.ver%100,LuoHe_version.time,LuoHe_version.v_crc);
  320. }
  321. }
  322. if(start_flag == 0)
  323. {
  324. //第1次运行,初始化 adc_rp
  325. start_flag++;
  326. adc_wp = ret;
  327. adc_rp = ret;
  328. }
  329. else
  330. {
  331. adc_wp = ret;
  332. }
  333. if(adc_wp>=SHM_ADC_WR_NUM)
  334. {
  335. adc_wp=0;
  336. }
  337. if(adc_rp>=SHM_ADC_WR_NUM)
  338. {
  339. adc_rp=0;
  340. }
  341. while(adc_wp!=adc_rp)
  342. {
  343. opt=((g_adc_dots_data_count&(ADC_REC_SAMPLE_RATE-1))==0)?TRUE:FALSE;
  344. ret = get_adc_sample(SHM_ADDR_U_ADC_1, adc_rp,(uint8_t *)&sample_data[0]);
  345. ret = get_adc_sample(SHM_ADDR_U_ADC_2, adc_rp,(uint8_t *)&sample_data[1]);
  346. if(ret < 0)
  347. {
  348. if(++cnt > 3)
  349. {
  350. rt_printf("get_adc_sample 返回错误值, ret=%d!\r\n",ret);
  351. break;
  352. }
  353. continue;
  354. }
  355. //保存yx值
  356. g_yx_buf[0] = sample_data[0].yx_buf[0];
  357. g_yx_buf[1] = sample_data[1].yx_buf[1];
  358. if(!recv_init)
  359. {
  360. recv_init = 1;
  361. //开机时裸核还没有把遥信送上下,这里重新初始化plc_init
  362. // dido_init_di(); //TODO EWen 集中式采用开入开出子板形式采集遥信
  363. // plc_init(); TODO EWen
  364. }
  365. // 标准化DTU遥信已经经过开入子板处理防抖
  366. // dido_di_poll(&sample_data[0]);
  367. for(i=0; i<16; i++)
  368. {
  369. g_adc_dots_rec[g_adc_dots_index_rec][i] = sample_data[0].sample_buf[i];
  370. if(opt==TRUE)
  371. {
  372. g_adc_dots[i][g_adc_dots_index] = sample_data[0].sample_buf[i];
  373. ts_adc_dots[g_adc_dots_index] = sample_data[0].ts;
  374. }
  375. }
  376. for(i=16; i<CFG_ADC_CHANNEL; i++)
  377. {
  378. g_adc_dots_rec[g_adc_dots_index_rec][i] = sample_data[1].sample_buf[i - 16];
  379. if(opt==TRUE)
  380. {
  381. g_adc_dots[i][g_adc_dots_index] = sample_data[1].sample_buf[i - 16];
  382. ts_adc_dots[g_adc_dots_index] = sample_data[1].ts;
  383. }
  384. }
  385. g_adc_dots_dc[0][g_adc_dots_data_count&CFG_ADC_DOTS_MASK] = sample_data[0].sample_buf[AD7616_DC0_CHANNEL];
  386. // g_adc_dots_dc[1][g_adc_dots_data_count&CFG_ADC_DOTS_MASK] = sample_data.sample_buf[AD7616_DC0_CHANNEL];
  387. if(opt==TRUE)
  388. {
  389. index = g_adc_dots_index;
  390. // 统计数据
  391. if(g_adc_stat_flag)
  392. {
  393. for(i=0; i<CFG_ADC_CHANNEL; i++)
  394. {
  395. rt_stat_in(&g_stat_adc[i],(unsigned short)(g_adc_dots[i][index]+32768));
  396. }
  397. }
  398. // 通道取反
  399. for(i=0; i<g_equ_adc_inv_num; i++)
  400. {
  401. g_adc_dots[g_equ_adc_inv[i]][index] = -(g_adc_dots[g_equ_adc_inv[i]][index]);
  402. }
  403. // 全部BUFFER都是新数据,才能算同步好。
  404. if(g_adc_sync < 1)
  405. {
  406. g_adc_sync ++;
  407. }
  408. // 索引值加一
  409. g_adc_dots_count++;
  410. //保护计数+突变量
  411. {
  412. dTCounter++;
  413. if(dTCounter%8==0)
  414. {
  415. prt_flag=true;
  416. }
  417. //突变量
  418. if(g_adc_sync == 1 && g_sw_init == 1)
  419. {
  420. protect_tbl_qd();
  421. }
  422. }
  423. }
  424. g_adc_dots_data_count++;
  425. if(++adc_rp>=SHM_ADC_WR_NUM)
  426. adc_rp=0;
  427. }
  428. return 0;
  429. }
  430. /******************************************************************************
  431. 函数名称: adc_slot_is_ok
  432. 函数版本: 01.01
  433. 创建作者: sunxi
  434. 创建日期: 2016-02-01
  435. 函数说明: 检查对应槽的ADC芯片是否安装或损坏。
  436. 参数说明:
  437. slot: 0~3;从g_ac_slot_begin开始
  438. 返回值: 成功返回0.
  439. 修改记录:
  440. */
  441. int adc_slot_is_ok(int slot)
  442. {
  443. if((u32)slot >= EQU_SLOT_AC_NUM)
  444. {
  445. return 0;
  446. }
  447. if(g_adc_chip & (1<<g_adc_slot2cs[slot]))
  448. {
  449. return 1;
  450. }
  451. return 0;
  452. }
  453. /******************************************************************************
  454. 函数名称: adc_fourier_address
  455. 函数版本: 01.01
  456. 创建作者: sunxi
  457. 创建日期: 2008-06-26
  458. 函数说明: 返回指定的通道进行傅立叶计算的首地址。首地址保证4bytes对齐。
  459. 参数说明:
  460. channel:ADC的通道,取值0~7。
  461. index: 要进行傅立叶计算的32点中的最后一个点的索引。这么设置是为了和
  462. g_adc_dots_index匹配。保证g_adc_dots_index可以直接作为参数传进来。
  463. 返回值: 成功返回0.
  464. 修改记录:
  465. */
  466. #if 0
  467. short * adc_fourier_address(int channel,int index)
  468. {
  469. short *p;
  470. //{index + CFG_ADC_DOTS_PER_CHANNEL}是为了确保索引在相应的范围之内.
  471. index = index + CFG_ADC_DOTS_PER_CHANNEL - CFG_ADC_DOTS_PER_PERIOD;
  472. //使用偶数索引,保证4bytes对齐
  473. index &= (~0x1);
  474. //得到首地址,注意地址必须和CFG_ADC_BUF_MASK相与。
  475. p = (short *)&g_adc_dots[channel][index];
  476. p = (short *)((unsigned int)p&CFG_ADC_BUF_MASK);
  477. return p;
  478. }
  479. #else
  480. short sam_buf[CFG_ADC_CHANNEL][CFG_ADC_DOTS_PER_PERIOD];
  481. short * adc_fourier_address(int channel,int index)
  482. {
  483. short *p;
  484. int i;
  485. if(index >= CFG_ADC_DOTS_PER_PERIOD)
  486. {
  487. index = index - CFG_ADC_DOTS_PER_PERIOD;
  488. index &= (~0x1);
  489. p = (short *)&g_adc_dots[channel][index];
  490. }
  491. else
  492. {
  493. index = CFG_ADC_DOTS_PER_CHANNEL-CFG_ADC_DOTS_PER_PERIOD+index;
  494. index &= (~0x1);
  495. for(i = 0;i < CFG_ADC_DOTS_PER_CHANNEL - index;i++)
  496. {
  497. sam_buf[channel][i] = g_adc_dots[channel][index+i];
  498. }
  499. for(i = 0;i <CFG_ADC_DOTS_PER_PERIOD +index-CFG_ADC_DOTS_PER_CHANNEL;i++)
  500. {
  501. sam_buf[channel][i+CFG_ADC_DOTS_PER_CHANNEL - index] = g_adc_dots[channel][i];
  502. }
  503. p = sam_buf[channel];
  504. }
  505. return p;
  506. }
  507. #endif
  508. /******************************************************************************
  509. 函数名称: adc_fourier_address_half
  510. 函数版本: 01.01
  511. 创建作者: sunxi
  512. 创建日期: 2008-06-26
  513. 函数说明: 返回指定的通道进行傅立叶计算的首地址。首地址保证4bytes对齐。
  514. 参数说明:
  515. channel:ADC的通道,取值0~7。
  516. index: 要进行傅立叶计算的32点中的最后一个点的索引。这么设置是为了和
  517. g_adc_dots_index匹配。保证g_adc_dots_index可以直接作为参数传进来。
  518. 返回值: 成功返回0.
  519. 修改记录:
  520. */
  521. short * adc_fourier_address_half(int channel,int index)
  522. {
  523. short *p;
  524. //{index - (CFG_ADC_DOTS_PER_PERIOD - 1)}是因为索引下有实际的采样值,所以不是
  525. // index - CFG_ADC_DOTS_PER_PERIOD.
  526. //{index + CFG_ADC_DOTS_PER_CHANNEL}是为了确保索引在相应的范围之内.
  527. index = index + CFG_ADC_DOTS_PER_CHANNEL - (CFG_ADC_DOTS_PER_PERIOD/2 - 1);
  528. //使用偶数索引,保证4bytes对齐
  529. index &= (~0x1);
  530. //得到首地址,注意地址必须和CFG_ADC_BUF_MASK相与。
  531. p = (short *)&g_adc_dots[channel][index];
  532. p = (short *)((unsigned int)p&CFG_ADC_BUF_MASK);
  533. return p;
  534. }
  535. int adc_stat_printf(void)
  536. {
  537. int i;
  538. unsigned long avg = 0;
  539. struct rt_stat *stat;
  540. if(g_adc_stat_flag == 0)
  541. {
  542. g_adc_stat_flag = 1;
  543. rt_printf("\r\n!!!ADC采样统计启动, 执行reset命令关闭。!!!\r\n");
  544. }
  545. rt_printf("\r\n频率跟踪:%fHZ.\r\n",g_freq);
  546. rt_printf("g_adc_chip:0x%02x.\r\n",g_adc_chip);
  547. for(i=0;i<EQU_SLOT_AC_NUM;i++)
  548. {
  549. rt_printf("槽[%02lu]: 是否有对应芯片:%d,输入范围:0x%08lx.\r\n",g_ac_slot_begin+i,adc_slot_is_ok(i),g_adc_range[g_adc_slot2cs[i]]);
  550. }
  551. rt_printf("\r\n[ADC中断周期统计]\r\n");
  552. rt_printf("name\t\t\tmin\tmax\tavg\tsum\t\tcnt\n");
  553. // rt_stat_printf(&g_stat_adc_time);
  554. rt_printf("\r\n[ADC抖动统计]\r\n");
  555. rt_printf("name\t\t\tmin\tmax\tdif\tavg\tsum\t\tcnt\n");
  556. rt_printf("\r\n");
  557. for(i=0; i<CFG_ADC_CHANNEL_ALL; i++)
  558. {
  559. stat = &g_stat_adc[i];
  560. if(stat->cnt)
  561. {
  562. avg = stat->sum/stat->cnt;
  563. }
  564. 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);
  565. }
  566. return 0;
  567. }
  568. int adc_stat_reset(void)
  569. {
  570. int i;
  571. g_adc_stat_flag = 0;
  572. for(i=0; i<CFG_ADC_CHANNEL_ALL; i++)
  573. {
  574. rt_stat_init(&g_stat_adc[i],g_stat_adc[i].name);
  575. }
  576. // rt_stat_init(&g_stat_adc_time,g_stat_adc_time.name);
  577. return 0;
  578. }
  579. #if 0
  580. static int get_adc_dc(uint8_t *out_data)
  581. {
  582. int ret = 0;
  583. int cnt = 0;
  584. if(out_data == NULL)
  585. return -1;
  586. while(1)
  587. {
  588. ret = shm_comm_packet_read(SHM_ADDR_U_DC, sizeof(SHM_DC_T), out_data, sizeof(SHM_DC_T));
  589. if(ret > 0)
  590. {
  591. break;
  592. }
  593. if(++cnt > 3)
  594. break;
  595. usleep(30);
  596. }
  597. return ret;
  598. }
  599. #endif
  600. float dc_get(unsigned int index)
  601. {
  602. u32 i,v;
  603. float f;
  604. v = 0;
  605. for(i=0;i<CFG_ADC_DOTS_PER_CHANNEL;i++)
  606. {
  607. v += (u16)g_adc_dots_dc[index][i];
  608. }
  609. f = (float)v/CFG_ADC_DOTS_PER_CHANNEL;
  610. // 乘理论系数
  611. f /= 129.791f;
  612. return f;
  613. }
  614. /*------------------------------ 测试函数 -------------------------------------
  615. */
  616. #ifdef _ADC_DEBUG
  617. int adc_test(void)
  618. {
  619. return 0;
  620. }
  621. #endif
  622. /*------------------------------ 文件结束 -------------------------------------
  623. */