tdc_ms1030.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. #include "board.h"
  2. #include "tdc_tof.h"
  3. #define ANZ_FIRE 12u//fire发送脉冲数
  4. #define DIV_FIRE 3u //内部时钟产生脉冲的分频
  5. #define DIV_CLKHS 0u //高速时钟分频
  6. #define START_CLKHS 2u //高速启动后测量前晶振启动间隔时间,120us;0关闭,1持续开启,2延迟120us后开启
  7. #define NEG_START 0u //start通道边缘
  8. #define NEG_STOP 0u //stop通道边缘
  9. #define HITIN 9u //stop预期脉冲数
  10. #define SEL_TIMO_MB 3u //测量范围溢出时间暂未确定数值
  11. #define SEL_TSTO2 3u //32khz //和MS1030不同
  12. #define SEL_TSTO1 0u //暂时不用这个引脚,配置为高速时钟输入模式
  13. #define DFLT_WREG0 ((ANZ_FIRE<<25) | \
  14. ( DIV_FIRE<<19) | \
  15. ( DIV_CLKHS<<17) | \
  16. ( START_CLKHS<<14) | \
  17. ( NEG_START<<13) | \
  18. ( NEG_STOP<<12) | \
  19. ( HITIN<< 8) | \
  20. ( SEL_TIMO_MB<< 4) | \
  21. ( SEL_TSTO2<< 2) | \
  22. ( SEL_TSTO1<< 0))
  23. #define EN_INT_TO 1 //TIMOUT中断触发位
  24. #define EN_INT_HIT 0 //END HITS中断触发位
  25. #define EN_INT_ALU 1 //alu中断触发位
  26. #define RFEDGE 0 //stop通道边沿敏感性
  27. #define UP_DELVAL1 200 //当EN_FIST_WAVE=1时,为第一波屏蔽窗口 BIT12~27 暂未设置
  28. #define OFFSET 0 //当en_hc=1时, 62~-64mV 暂未设置
  29. #define DFLT_WREG1 (( EN_INT_TO<<31) | \
  30. ( EN_INT_HIT<<30) | \
  31. ( EN_INT_ALU<<29) | \
  32. ( RFEDGE<<28) | \
  33. ( UP_DELVAL1<<12) | \
  34. ( OFFSET<< 0))
  35. #define EN_FIRST_WAVE 1u //BIT31, 为1时后面的定义有效
  36. #define EDGE_FW 0u //第一波边缘敏感性
  37. #define DELREL1 6u //第1个stop接收第几个回波周期
  38. #define DELREL2 8u //第2个stop接收第几个回波周期
  39. #define DELREL3 10u //第3个stop接收第几个回波周期
  40. #define DELREL4 12u //第4个stop接收第几个回波周期
  41. #define DELREL5 14u //第5个stop接收第几个回波周期
  42. #define DFLT_WREG2 ((EN_FIRST_WAVE<<31)| \
  43. (EDGE_FW<<30) | \
  44. (DELREL1<<24) | \
  45. (DELREL2<<18) | \
  46. (DELREL3<<12) | \
  47. (DELREL4<< 6) | \
  48. (DELREL5<< 0))
  49. #define DELREL6 16u //第3个stop接收第几个回波周期
  50. #define DELREL7 18u //第4个stop接收第几个回波周期
  51. #define DELREL8 20u //第5个stop接收第几个回波周期
  52. //#define DIS_PW 0u //关闭脉冲宽度测量功能,0=开启
  53. //#define WAVE_OFFS 16u //第一波比较器偏置电压:EN_HC = 0 -64mV~63mV,10mv
  54. #define DFLT_WREG3 ((DELREL6<<26) | \
  55. (DELREL7<<20) | \
  56. (DELREL8<<14))
  57. // (DIS_PW<<13) | \
  58. // (WAVE_OFFS<<6))
  59. #define CONF_FIRE 2 //脉冲触发器的输出设置,暂时设置为0 bit29~31
  60. #define PHASE_FIREUP 0 //FIREUP反向设置
  61. #define PHASE_FIREDOWN 0 //FIREDOWN反向设置
  62. #define SEL_START_FIRE 1 //FIRE脉冲用作触发TDCSTART
  63. #define EN_ANALOG 1 //模拟测量控制开关
  64. #define HZ60 0 //顺流测量和逆流测量的时间单位
  65. #define TCYCLE 1 //温度测量循环时间
  66. #define ANZ_FAKE 0 //温度测量热身次数,0:两次热身,1:7次热身
  67. #define SEL_ECLK_TMP 1 //选择温度测量内部参考时钟
  68. #define TW2 5 //180us充电时间,与1030不同
  69. #define EN_PEAK 0 //峰值检波使能关闭,1030不同
  70. #define EN_DISCHARGE 0 //检波放电使能关闭,1030不同
  71. #define CYCLE_TOF 0 //顺流逆流自动检测模式下,顺流逆流测量间隔时间,初步确定为3=20ms 1030不同
  72. #define EN_ERR_VAL 1 //溢出时alu将全f写到结果寄存器
  73. #define EN_DC 1 //stop端口充电模式 这里设置为直流 1030不同
  74. #define FIRE0_DEF 1 //fire通道默认状态,fire通道默认电平
  75. #define DOUBLE_RES 0 //双精度模式
  76. #define QUAD_RES 1 //4精度模式
  77. #define DFLT_WREG4 (( CONF_FIRE<<29) | \
  78. ( PHASE_FIREUP<<28) | \
  79. ( PHASE_FIREDOWN<<27) | \
  80. ( SEL_START_FIRE<<26) | \
  81. ( EN_ANALOG<<25) | \
  82. ( HZ60<<24) | \
  83. ( TCYCLE<<23) | \
  84. ( ANZ_FAKE<<22) | \
  85. ( SEL_ECLK_TMP<<21) | \
  86. ( TW2<<17) | \
  87. ( EN_PEAK<<16) | \
  88. ( EN_DISCHARGE<<15) | \
  89. ( CYCLE_TOF<<11) | \
  90. ( EN_ERR_VAL<<10) | \
  91. ( EN_DC<<9) | \
  92. ( FIRE0_DEF<<8) | \
  93. ( DOUBLE_RES<<7) | \
  94. ( QUAD_RES<<6))
  95. #define CYCLE_AUTOTOF (250<<20) //自动测量循环时间 500ms
  96. #define ANZ_AUTOTOF (1<<16) //循环次数 一直开启
  97. #define AUTOTOF_MODE (0<<15) //顺逆顺逆
  98. #define PHASE_FIRENUM (3<<6) //插入相位位置
  99. #define ANZ_PHASE (8) //插入周期数
  100. #define DFLT_WREG5 0
  101. #define DOWN_DELVAL1 (200<<12) //逆流屏蔽窗口
  102. #define SEL_SRC_CLK (0<<7) //选择高速时钟输入源
  103. #define EN_HC (0<<6) //比较器调节步长
  104. #define CURR32K (0<<5) //32K晶振功耗设置
  105. #define DIS_Vref (1<<4) //基准电压输出控制
  106. #define ADJ_LDO_ROUGH (0<<3) //内部LDO输出粗调
  107. #define ADJ_LDO_FINE (0<<0) //内部LDO输出细调
  108. #define DFLT_WREG6 (DOWN_DELVAL1|SEL_SRC_CLK|EN_HC|CURR32K|DIS_Vref|ADJ_LDO_ROUGH|ADJ_LDO_FINE)
  109. uint16_t tof_state = TOF_ST_INIT;
  110. uint32_t tof_flag;
  111. //uint16_t CntSync = 0;
  112. void tdc_tof_init(void)
  113. {
  114. //MUX ADDA : PA08; ADDB : PC09
  115. mux_init();
  116. // MS1030 RSTN : PD02
  117. GpioInit(PD02_AF0, GPIO_DIG_OUT_WEAK_PUSH_NONEUP_NONEDOWN);
  118. GpioClrPins(GpioPortD, GpioBitMsk2); // reset active low
  119. us_delay(10); // 10us > tPH(30ns)
  120. GpioSetPins(GpioPortD, GpioBitMsk2); // reset release
  121. us_delay(10); // 10us > tRFS(30ns)
  122. tdc_spi_init(); // peripheral init
  123. PeriClk_MutEnable(PeriClk_Spi1);
  124. DMA_ReqClkOn();
  125. // TDC POR
  126. tdc_spi_wr_code(0x50);
  127. us_delay(1000); // 1000us > specification(500us)
  128. tdc_spi_wr_d32(0x80, DFLT_WREG0);
  129. uint32_t read_a0=tdc_spi_rd_d32(0xA0);
  130. read_a0=read_a0&0xFFu;
  131. #if 1
  132. tof_flag = TOF_FLAG_UNALGND_CHOP;
  133. if (read_a0!=(DFLT_WREG0&0xFFu)){
  134. tof_flag |= TOF_FLAG_TDC_FAULT;
  135. } else {
  136. // write_reg0
  137. tdc_spi_wr_d32(0x80, DFLT_WREG0);
  138. // write_reg1
  139. tdc_spi_wr_d32(0x81, DFLT_WREG1);
  140. // write_reg2
  141. tdc_spi_wr_d32(0x82, DFLT_WREG2);
  142. // write_reg3
  143. tdc_spi_wr_d32(0x83, DFLT_WREG3);
  144. // write_reg4
  145. tdc_spi_wr_d32(0x84, DFLT_WREG4);
  146. // write_reg5
  147. tdc_spi_wr_d32(0x85, DFLT_WREG5);
  148. // write_reg6
  149. tdc_spi_wr_d32(0x86, DFLT_WREG6);
  150. tdc_spi_wr_d32(0x87,0x20000000);//!!!!!!!!do not delete!!!!!!!!!
  151. tdc_spi_wr_code(0x70);
  152. tdc_spi_wr_code(0x06);
  153. // // not 'INTN' but 'us_delay' to avoid dead loop when INTN fault
  154. us_delay(2000); // > 480 + 600 + 16 + 70
  155. tdc_read_cal(0x0u);
  156. // tof_flag ^= TOF_FLAG_UNALGND_CHOP;
  157. // // start a single ToF to align MS1030 internal calibration order(1 CAL every 24 ToF)
  158. // // must be sure that CAL not in the middle of UP Tof and DOWN Tof
  159. // tdc_start_tof(TDC_CFG_DO_WREG | TDC_CFG_FIRE_UP);
  160. //
  161. // // not 'INTN' but 'us_delay' to avoid dead loop when INTN fault
  162. // us_delay(2000); // > 480 + 600 + 16 + 70
  163. //
  164. // tdc_read_tof(TDC_CFG_FIRE_UP); // read data and clear interrupt
  165. }
  166. #endif
  167. DMA_ReqClkOff();
  168. PeriClk_MutDisable(PeriClk_Spi1);
  169. // MS1030 INTN : PD03 falling edge trigger
  170. GpioInit(PD03_AF0, GPIO_DIG_IN_PULLUP_NONEDOWN);
  171. GpioEventInit(PD03_AF0, GPIO_EVENT_FALL);
  172. // enable interrupt at NVIC side
  173. IRQMutEnable(PORTD_F_IRQn, NVIC_PRIO_1);
  174. }
  175. void tdc_start_tof(uint32_t cfg)
  176. {
  177. //rt_enter_critical();
  178. uint32_t u32tmp;
  179. if (cfg & TDC_CFG_DO_CKENA){
  180. PeriClk_MutEnable(PeriClk_Spi1);
  181. DMA_ReqClkOn();
  182. }
  183. if (cfg & TDC_CFG_DO_WREG){
  184. u32tmp = (DFLT_WREG3 & ~(1u << 13)) | (TdcFwOfst << 6);
  185. // measure FW pulse width, 0:on; 1:off
  186. // FW wave_offs, 0:0mv; 1~63:2~126mV; 64~127:-128~-2mV;
  187. if (tof_state&TOF_ST_VOID){
  188. u32tmp |= (1u<<13); // disable FW pulse width to save power
  189. }
  190. tdc_spi_wr_d32(0x83, u32tmp);
  191. }
  192. // Initial TDC status regs
  193. tdc_spi_wr_code(0x70);
  194. // start single-direction measure
  195. tdc_spi_wr_code(0x03);
  196. if (cfg & TDC_CFG_DO_CKDIS){
  197. DMA_ReqClkOff();
  198. PeriClk_MutDisable(PeriClk_Spi1);
  199. }
  200. //rt_exit_critical();
  201. }
  202. uint16_t TdcStatus;
  203. uint16_t TdcUPwFw;
  204. uint16_t TdcUPwHw;
  205. uint32_t TdcUToF[9];
  206. uint16_t TdcDPwFw;
  207. uint16_t TdcDPwHw;
  208. uint32_t TdcDToF[9];
  209. uint32_t TdcCal;
  210. //float TdcScale = 250.0f/65536;
  211. float TdcScale = 0.00381147861f;
  212. uint32_t TdcPT[4];
  213. float TdcResist = 5000; // OhmX10
  214. //modified by yuewei 20260520
  215. //float WaterPrmt[2] = {25.0f, 1496.6f};
  216. float WaterPrmt[2] = {25.0f, 1497.1484f};
  217. void tdc_read_tof(uint32_t cfg)
  218. {
  219. // uint16_t i;
  220. if (cfg & TDC_CFG_DO_CKENA){
  221. PeriClk_MutEnable(PeriClk_Spi1);
  222. DMA_ReqClkOn();
  223. }
  224. TdcStatus = tdc_spi_rd_d16(0xd0); // 读取状态寄存器
  225. if ((TdcStatus&0x0300)==0x0000u){
  226. tof_flag ^= TOF_FLAG_UNALGND_CHOP;
  227. }
  228. if ((TdcStatus&0x03F0)!=0x0090u){
  229. tof_flag |= TOF_FLAG_BLANK_PIPE;
  230. tdc_spi_wr_code(0x70);
  231. tdc_spi_wr_d32(0x80, DFLT_WREG0 & ~(0x07 << 14)); //一旦为空管马上关闭高速晶振,降低功耗
  232. }
  233. else
  234. {
  235. TdcUPwFw = tdc_spi_rd_d16(0xd3); // First wave pulse width
  236. TdcUPwHw = tdc_spi_rd_d16(0xd4); // 1st Hit wave pulse width
  237. TdcDPwFw = tdc_spi_rd_d16(0xd3);
  238. TdcDPwHw = tdc_spi_rd_d16(0xd4);
  239. // TOF_UP_HITs
  240. TdcUToF[0] = tdc_spi_rd_d32(0xb8)*(1.0f/8); // average of all
  241. // TOF_DOWN_HITs
  242. TdcDToF[0] = tdc_spi_rd_d32(0xc8)*(1.0f/8); // average of all
  243. // for(i=0; i<8; i++){
  244. // TdcDToF[i+1] = tdc_spi_rd_d32(0xb0 + i);
  245. // };
  246. }
  247. if (cfg & TDC_CFG_DO_CKDIS){
  248. DMA_ReqClkOff();
  249. PeriClk_MutDisable(PeriClk_Spi1);
  250. }
  251. }
  252. void tdc_start_cal(uint32_t cfg)
  253. {
  254. //rt_enter_critical();
  255. if (cfg & TDC_CFG_DO_CKENA){
  256. PeriClk_MutEnable(PeriClk_Spi1);
  257. DMA_ReqClkOn();
  258. }
  259. // 8*T_32k = 244.140625us
  260. if (cfg & TDC_CFG_DO_WREG){
  261. // write_reg0
  262. // tdc_spi_wr_d32(0x80, DFLT_WREG0 |
  263. // ( 2u<< 4) // SEL_TIMO_MB, 0:64us; 1:128us; 2:256us; ~ 6:4096us;
  264. // );
  265. // write_reg3
  266. tdc_spi_wr_d32(0x83, DFLT_WREG3 |
  267. ( 1u<<13) // measure FW pulse width, 0:on; 1:off
  268. );
  269. }
  270. tdc_spi_wr_code(0x70);
  271. tdc_spi_wr_code(0x06);
  272. if (cfg & TDC_CFG_DO_CKDIS){
  273. DMA_ReqClkOff();
  274. PeriClk_MutDisable(PeriClk_Spi1);
  275. }
  276. //rt_exit_critical();
  277. }
  278. void tdc_read_cal(uint32_t cfg)
  279. {
  280. //rt_enter_critical();
  281. if (cfg & TDC_CFG_DO_CKENA){
  282. PeriClk_MutEnable(PeriClk_Spi1);
  283. DMA_ReqClkOn();
  284. }
  285. TdcStatus = tdc_spi_rd_d16(0xd0); // status
  286. if ((TdcStatus&0x0300)==0x0000u){
  287. tof_flag ^= TOF_FLAG_UNALGND_CHOP;
  288. TdcCal = tdc_spi_rd_d32(0xd5);
  289. // TdcScale = 244140.625f/TdcCal;
  290. TdcScale += (244140.625f/TdcCal - TdcScale)*(1.0f/2);
  291. //LOG("----------TdcScale=%.6f\n",TdcScale);
  292. } else {
  293. // tdc_spi_wr_code(0x70);
  294. }
  295. if (cfg & TDC_CFG_DO_CKDIS){
  296. DMA_ReqClkOff();
  297. PeriClk_MutDisable(PeriClk_Spi1);
  298. }
  299. //rt_exit_critical();
  300. }
  301. void tdc_start_temp(uint32_t cfg)
  302. {
  303. //rt_enter_critical();
  304. if (cfg & TDC_CFG_DO_CKENA){
  305. PeriClk_MutEnable(PeriClk_Spi1);
  306. DMA_ReqClkOn();
  307. }
  308. if (cfg & TDC_CFG_DO_WREG){
  309. // tdc_spi_wr_d32(0x80, DFLT_WREG0 |
  310. // ( 3u<< 6) // SEL_TIMO_MB, 0:64us; 1:128us; 2:256us; 3:512us; ~ 6:4096us;
  311. // );
  312. // // write_reg1
  313. // tdc_spi_wr_d32(0x81, DFLT_WREG1 |
  314. // ( 0u<< 12) // DELVAL1=0us, format:16.5, time unit:Tref;
  315. // );
  316. // write_reg3
  317. tdc_spi_wr_d32(0x83, DFLT_WREG3 |
  318. ( 1u<<13) // measure FW pulse width, 0:on; 1:off
  319. );
  320. }
  321. tdc_spi_wr_code(0x70);
  322. tdc_spi_wr_code(0x04);
  323. if (cfg & TDC_CFG_DO_CKDIS){
  324. DMA_ReqClkOff();
  325. PeriClk_MutDisable(PeriClk_Spi1);
  326. }
  327. //rt_exit_critical();
  328. }
  329. uint8_t temp_error_flag=0;
  330. void tdc_read_temp(uint32_t cfg)
  331. {
  332. if (cfg & TDC_CFG_DO_CKENA){
  333. PeriClk_MutEnable(PeriClk_Spi1);
  334. DMA_ReqClkOn();
  335. }
  336. TdcStatus = tdc_spi_rd_d16(0xd0); // status
  337. TdcPT[0] = tdc_spi_rd_d32(0xd1); // REF 5K +/- 5
  338. TdcPT[1] = tdc_spi_rd_d32(0xd2); // U7
  339. if(TdcPT[0]==0xffffffff || TdcPT[1]==0xffffffff || TdcPT[0] ==0x00000000 || TdcPT[1]==0x00000000)
  340. {
  341. temp_error_flag=1;
  342. }
  343. else
  344. {
  345. temp_error_flag=0;
  346. TdcResist = 2500.0f*TdcPT[1]/TdcPT[0]; // ohmX10
  347. Ohm2Dgr2USSpd(TdcResist, WaterPrmt); // [0]:Temperature; [1]:ultrasonic speed @Temp
  348. }
  349. if (cfg & TDC_CFG_DO_CKDIS){
  350. DMA_ReqClkOff();
  351. PeriClk_MutDisable(PeriClk_Spi1);
  352. }
  353. }
  354. void MS1031_DisableHighSpeedOsc(void)
  355. {
  356. PeriClk_MutEnable(PeriClk_Spi1);
  357. DMA_ReqClkOn();
  358. tdc_spi_wr_d32(0x80, DFLT_WREG0 & ~(0x07 << 14)); //一旦为空管马上关闭高速晶振,降低功耗
  359. DMA_ReqClkOff();
  360. PeriClk_MutDisable(PeriClk_Spi1);
  361. }
  362. void MS1031_EnableHighSpeedOsc(void)
  363. {
  364. PeriClk_MutEnable(PeriClk_Spi1);
  365. DMA_ReqClkOn();
  366. GpioClrPins(GpioPortD, GpioBitMsk2);
  367. us_delay(10);
  368. GpioSetPins(GpioPortD, GpioBitMsk2);
  369. us_delay(10);
  370. tdc_spi_wr_d32(0x80,DFLT_WREG0);
  371. tdc_spi_wr_d32(0x81,DFLT_WREG1);
  372. tdc_spi_wr_d32(0x82,DFLT_WREG2);
  373. tdc_spi_wr_d32(0x83,DFLT_WREG3);
  374. tdc_spi_wr_d32(0x84,DFLT_WREG4);
  375. tdc_spi_wr_d32(0x85,DFLT_WREG5);
  376. tdc_spi_wr_d32(0x86,DFLT_WREG6);
  377. tdc_spi_wr_d32(0x87,0x20000000);//!!!!!!!!do not delete!!!!!!!!!
  378. DMA_ReqClkOff();
  379. PeriClk_MutDisable(PeriClk_Spi1);
  380. }