ad7616.c 20 KB

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