analog_input.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. #include "at32f403a_407.h"
  2. #include "analog_input.h"
  3. #include "shift_reg.h"
  4. #include "utility.h"
  5. #include "FreeRTOS.h"
  6. #include "task.h"
  7. #include "settings_api.h"
  8. #include "adc_transport.h"
  9. #include "ms5192t.h"
  10. #include "monitoring.h"
  11. #include "mux.h"
  12. #include <stdio.h>
  13. #undef DBG
  14. #define DBG if(1)
  15. #if defined (MAI_12)
  16. uint8_t ai_mux; // выход сдвигового регистра U1010 (управляет MUX 301, 401)
  17. // мультиплексоры отвечат за коммутацию аналоговых входов и АЦП
  18. uint16_t ai_mode; // режим измерения аналоговых каналов (ток или напряжение)
  19. // 0000 0000 0000 0000
  20. // младшие 6 (с 1..6) бит - каналы с 1 по 6 соответственно
  21. // биты 9..14 - каналы с 7 по 12 соответственно
  22. uint16_t ai_alarm; // слово аварий входов
  23. ANALOG_IN_t channel_name[NUMBER_ADC_CH] = {AN_INP_1, AN_INP_2, AN_INP_3,
  24. AN_INP_4, AN_INP_5, AN_INP_6,
  25. V_ISO_CL, V_ISO,
  26. AN_INP_7, AN_INP_8, AN_INP_9,
  27. AN_INP_10, AN_INP_11, AN_INP_12,
  28. CRNT_LIM_U_BFR_R, CRNT_LIM_U_ABFR_R};
  29. uint16_t adc_raw_data[NUMBER_ADC_CH];
  30. led_t ai_alarm_led[12] = {IO_1_R, IO_2_R, IO_3_R, IO_4_R,
  31. IO_5_R, IO_6_R, IO_7_R, IO_8_R,
  32. IO_9_R, IO_10_R, IO_11_R, IO_12_R};
  33. //
  34. void ai_init(void)
  35. {
  36. sh_init(); // Сдвиговые регистры
  37. ai_set_meas_mode(); // Режим измерения
  38. ai_ext_sens_power(settings.ext_sens_power); // Питание внешних датчиков
  39. ai_adc_init(); // Внешинй ADC
  40. }
  41. // Установить режим измерения каналов с 1 по 12.
  42. void ai_set_meas_mode(void)
  43. {
  44. for (uint8_t i = 1; i < 13; i++)
  45. {
  46. if (settings.ai_mode_bits & (1 << (i - 1)))
  47. ai_set_mode_word((MEAS_CHAN_MODE_t)1, i);
  48. else
  49. ai_set_mode_word((MEAS_CHAN_MODE_t)0, i);
  50. }
  51. }
  52. // Настройка внешнего ADC
  53. bool ai_adc_init(void)
  54. {
  55. uint8_t ret;
  56. unsigned long value;
  57. adc_gpio_init();
  58. for (uint32_t i = 0; i < 100; i++) {
  59. MS5192T_Reset();
  60. ret = MS5192T_Init();
  61. DBG printf("ADC init status: %s\r\n", ret == 1 ? "OK" : "FAILED");
  62. if (ret == 1)
  63. break;
  64. vTaskDelay(10);
  65. }
  66. if (!ret) {
  67. mon_set_err(ERR_WORD_1, ADC_ERR, true);
  68. return false;
  69. }
  70. // Запрос регистра конфигурации для (0x710 - значение по умолчанию)
  71. value = MS5192T_GetRegisterValue(MS5192T_REG_CONF, 2, 1);
  72. DBG printf("ADC cfg reg: 0x%X: ", value);
  73. DBG print_binary_half_word((uint16_t)value);
  74. // Коэф-т усиления: 1
  75. DBG printf("ADC. Set gain rate 1\r\n");
  76. MS5192T_SetGain(MS5192T_GAIN_1);
  77. value = MS5192T_GetRegisterValue(MS5192T_REG_CONF, 2, 1);
  78. DBG printf("ADC cfg reg: 0x%X: ", value);
  79. DBG print_binary_half_word((uint16_t)value);
  80. // Униполярный режим
  81. DBG printf("Set unipolar input mode...\r\n");
  82. MS5192T_SetPolar(MS5192T_CONF_UNIPOLAR);
  83. value = MS5192T_GetRegisterValue(MS5192T_REG_CONF, 2, 1);
  84. DBG printf("ADC cfg reg: 0x%X: ", value);
  85. DBG print_binary_half_word((uint16_t)value);
  86. // Регистр статуса
  87. value = MS5192T_GetRegisterValue(MS5192T_REG_STAT, 1, 1);
  88. DBG printf("ADC status reg: 0x%X: ", value);
  89. DBG print_binary_byte((uint8_t)value);
  90. // Установка внутреннего опорного напряжения
  91. MS5192T_SetIntReference(MS5192T_REFSEL_INT); // select internal 1.17V reference
  92. value = MS5192T_GetRegisterValue(MS5192T_REG_CONF, 2, 1);
  93. DBG printf("ADC cfg reg: 0x%X: ", value);
  94. DBG print_binary_half_word((uint16_t)value);
  95. // Регистр режима (MODE register)
  96. value = MS5192T_GetRegisterValue(MS5192T_REG_MODE, 2, 1);
  97. DBG printf("ADC mode reg: 0x%X: ", value);
  98. DBG print_binary_half_word((uint16_t)value);
  99. // Установить update rate
  100. DBG printf("Set update rate.\r\n");
  101. MS5192T_SetUpdateRate(MS5192T_UP_RATE_500);
  102. value = MS5192T_GetRegisterValue(MS5192T_REG_MODE, 2, 1);
  103. DBG printf("ADC mode reg: 0x%X: ", value);
  104. DBG print_binary_half_word((uint16_t)value);
  105. // Калибровка
  106. // 1 - ый канал
  107. MS5192T_Calibrate(MS5192T_MODE_CAL_INT_ZERO, MS5192T_CH_AIN1P_AIN1M);
  108. MS5192T_Calibrate(MS5192T_MODE_CAL_INT_FULL, MS5192T_CH_AIN1P_AIN1M);
  109. // 2 - ой канал
  110. MS5192T_Calibrate(MS5192T_MODE_CAL_INT_ZERO, MS5192T_CH_AIN2P_AIN2M);
  111. MS5192T_Calibrate(MS5192T_MODE_CAL_INT_FULL, MS5192T_CH_AIN2P_AIN2M);
  112. return true;
  113. }
  114. // Оцифровка всех каналов (входы + дополнительные каналы)
  115. void ai_processing(void)
  116. {
  117. for (uint8_t i = 0; i < 8; i++)
  118. {
  119. adc_get_two_channles(channel_name[i], channel_name[i + 8]);
  120. }
  121. #if 0
  122. printf("end\r\n");
  123. adc_print_data();
  124. printf("end\r\n");
  125. #endif
  126. }
  127. //
  128. void adc_get_two_channles(ANALOG_IN_t one, ANALOG_IN_t two)
  129. {
  130. ai_connect_channel(one);
  131. vTaskDelay(1);
  132. MS5192T_SetChannel(MS5192T_CH_AIN1P_AIN1M);
  133. adc_raw_data[one] = MS5192T_SingleConversion();
  134. ai_connect_channel(two);
  135. vTaskDelay(1);
  136. MS5192T_SetChannel(MS5192T_CH_AIN2P_AIN2M);
  137. adc_raw_data[two] = MS5192T_SingleConversion();
  138. }
  139. //
  140. void adc_print_data(void)
  141. {
  142. printf("\033[2J"); // Очистить
  143. printf("\033[H"); // Переместить курсор в левый верхний угол
  144. printf("AN_INP_1: 0x%X, %f\r\n", adc_raw_data[AN_INP_1], (double) adc_raw_data[AN_INP_1]*0.00001785305/0.0961538);
  145. printf("AN_INP_2: 0x%X, %f\r\n", adc_raw_data[AN_INP_2], (double) adc_raw_data[AN_INP_2]*0.00001785305/0.0961538);
  146. printf("AN_INP_3: 0x%X, %f\r\n", adc_raw_data[AN_INP_3], (double) adc_raw_data[AN_INP_3]*0.00001785305/0.0961538);
  147. printf("AN_INP_4: 0x%X, %f\r\n", adc_raw_data[AN_INP_4], (double) adc_raw_data[AN_INP_4]*0.00001785305/0.0961538);
  148. printf("AN_INP_5: 0x%X, %f\r\n", adc_raw_data[AN_INP_5], (double) adc_raw_data[AN_INP_5]*0.00001785305/0.0961538);
  149. printf("AN_INP_6: 0x%X, %f\r\n", adc_raw_data[AN_INP_6], (double) adc_raw_data[AN_INP_6]*0.00001785305/0.0961538);
  150. printf("AN_INP_7: 0x%X, %f\r\n", adc_raw_data[AN_INP_7], (double) adc_raw_data[AN_INP_7]*0.00001785305/0.0961538);
  151. printf("AN_INP_8: 0x%X, %f\r\n", adc_raw_data[AN_INP_8], (double) adc_raw_data[AN_INP_8]*0.00001785305/0.0961538);
  152. printf("AN_INP_9: 0x%X, %f\r\n", adc_raw_data[AN_INP_9], (double) adc_raw_data[AN_INP_9]*0.00001785305/0.0961538);
  153. printf("AN_INP_10: 0x%X, %f\r\n", adc_raw_data[AN_INP_10], (double) adc_raw_data[AN_INP_10]*0.00001785305/0.0961538);
  154. printf("AN_INP_11: 0x%X, %f\r\n", adc_raw_data[AN_INP_11], (double) adc_raw_data[AN_INP_11]*0.00001785305/0.0961538);
  155. printf("AN_INP_12: 0x%X, %f\r\n", adc_raw_data[AN_INP_12], (double) adc_raw_data[AN_INP_12]*0.00001785305/0.0961538);
  156. printf("V_ISO_CL: 0x%X, %f\r\n", adc_raw_data[V_ISO_CL], (double) adc_raw_data[V_ISO_CL]*0.00001785305/0.0961538);
  157. printf("V_ISO: 0x%X, %f\r\n", adc_raw_data[V_ISO], (double) adc_raw_data[V_ISO]*0.00001785305/0.0961538);
  158. printf("CRNT_LIM_U_BFR_R: 0x%X, %f\r\n", adc_raw_data[CRNT_LIM_U_BFR_R], (double) adc_raw_data[CRNT_LIM_U_BFR_R]*0.00001785305/0.0961538);
  159. printf("CRNT_LIM_U_ABFR_R: 0x%X, %f\r\n", adc_raw_data[CRNT_LIM_U_ABFR_R], (double) adc_raw_data[CRNT_LIM_U_ABFR_R]*0.00001785305/0.0961538);
  160. }
  161. //
  162. void adc_task(void *params)
  163. {
  164. for (;;)
  165. {
  166. ai_alarm = sh_ai_mode(ai_mode);
  167. ai_processing();
  168. ai_leds_processing();
  169. //vTaskDelay(10);
  170. }
  171. }
  172. // Подключить канал к АЦП
  173. // Одновременно могут быть подключены только 2 канала из наборов:
  174. // 1: AN_INP_1, AN_INP_2, AN_INP_3, AN_INP_4, AN_INP_5, AN_INP_6, V_ISO_CL,
  175. // V_ISO
  176. //
  177. // 2: AN_INP_7, AN_INP_8, AN_INP_9, AN_INP_10, AN_INP_11, AN_INP_12,
  178. // CRNT_LIM_U_BFR_R, CRNT_LIM_U_ABFR_R
  179. void ai_connect_channel(uint8_t channel)
  180. {
  181. if (channel < MUX_401_CH)
  182. {
  183. ai_mux &= 0xF0;
  184. switch (channel)
  185. {
  186. case AN_INP_1: ai_mux |= 0x03; break; // U301 Y3
  187. case AN_INP_2: ai_mux |= 0x00; break; // U301 Y0
  188. case AN_INP_3: ai_mux |= 0x05; break; // U301 Y5
  189. case AN_INP_4: ai_mux |= 0x07; break; // U301 Y7
  190. case AN_INP_5: ai_mux |= 0x06; break; // U301 Y6
  191. case AN_INP_6: ai_mux |= 0x04; break; // U301 Y4
  192. case V_ISO_CL: ai_mux |= 0x01; break; // U301 Y1
  193. case V_ISO : ai_mux |= 0x02; break; // U301 Y2
  194. default: break;
  195. }
  196. }
  197. else
  198. {
  199. ai_mux &= 0x87;
  200. switch (channel)
  201. {
  202. case AN_INP_7: ai_mux |= (0x04 << 4); break; // U401 Y4
  203. case AN_INP_8: ai_mux |= (0x06 << 4); break; // U401 Y6
  204. case AN_INP_9: ai_mux |= (0x07 << 4); break; // U401 Y7
  205. case AN_INP_10:ai_mux |= (0x05 << 4); break; // U401 Y5
  206. case AN_INP_11:ai_mux |= (0x02 << 4); break; // U401 Y2
  207. case AN_INP_12:ai_mux |= (0x01 << 4); break; // U401 Y1
  208. case CRNT_LIM_U_BFR_R: ai_mux |= (0x00 << 4); break; // U401 Y0
  209. case CRNT_LIM_U_ABFR_R: ai_mux |= (0x03 << 4); break; // U401 Y3
  210. default: break;
  211. }
  212. }
  213. sh_ai_connect(ai_mux);
  214. //printf("Analog input connect register: ");
  215. //print_binary_byte(ai_mux);
  216. }
  217. // Утсновить режим измерения канала (ток или напряжение)
  218. void ai_set_mode(MEAS_CHAN_MODE_t mode, uint8_t channel)
  219. {
  220. if (mode == MEAS_CURRENT)
  221. {
  222. if (channel < 7)
  223. ai_mode |= (1 << (channel - 1));
  224. else
  225. ai_mode |= (1 << (channel + 1));
  226. }
  227. else
  228. if (channel < 7)
  229. ai_mode &= ~(1 << (channel - 1));
  230. else
  231. ai_mode &= ~(1 << (channel + 1));
  232. sh_ai_mode(ai_mode);
  233. //printf("Analog input mode: ");
  234. print_binary_half_word(ai_mode);
  235. }
  236. // Формируем слово режима работы каналов (ai_mode)
  237. void ai_set_mode_word(MEAS_CHAN_MODE_t mode, uint8_t channel)
  238. {
  239. if (mode == MEAS_CURRENT)
  240. {
  241. if (channel < 7)
  242. ai_mode |= (1 << (channel - 1));
  243. else
  244. ai_mode |= (1 << (channel + 1));
  245. }
  246. else
  247. if (channel < 7)
  248. ai_mode &= ~(1 << (channel - 1));
  249. else
  250. ai_mode &= ~(1 << (channel + 1));
  251. }
  252. // Сигнал питания внешних датчиков
  253. void ai_ext_sens_power(uint16_t state)
  254. {
  255. if (state)
  256. ai_mux |= 0x80;
  257. else
  258. ai_mux &= ~(0x80);
  259. }
  260. // Управления LED
  261. void ai_leds_processing(void)
  262. {
  263. //uint16_t foo = 0x800;
  264. // Управление индикацией аварий (12 красных LED) (слово ai_alarm)
  265. for (uint8_t i = 0; i < AI_NUMBER; i++) {
  266. if (ai_alarm & (1 << i)) {
  267. leds[ai_alarm_led[i]].state = LED_ON;
  268. }
  269. else {
  270. leds[ai_alarm_led[i]].state = LED_OFF;
  271. }
  272. }
  273. }
  274. //
  275. void ai_connect_test(void)
  276. {
  277. ai_connect_channel(AN_INP_1);
  278. ai_connect_channel(AN_INP_2);
  279. ai_connect_channel(AN_INP_3);
  280. ai_connect_channel(AN_INP_4);
  281. ai_connect_channel(AN_INP_5);
  282. ai_connect_channel(AN_INP_6);
  283. ai_connect_channel(V_ISO_CL);
  284. ai_connect_channel(V_ISO);
  285. ai_connect_channel(AN_INP_7);
  286. ai_connect_channel(AN_INP_8);
  287. ai_connect_channel(AN_INP_9);
  288. ai_connect_channel(AN_INP_10);
  289. ai_connect_channel(AN_INP_11);
  290. ai_connect_channel(AN_INP_12);
  291. ai_connect_channel(CRNT_LIM_U_BFR_R);
  292. ai_connect_channel(CRNT_LIM_U_ABFR_R);
  293. }
  294. //
  295. void ai_mode_test(void)
  296. {
  297. for (uint8_t i = 1; i < 13; i++)
  298. {
  299. ai_set_mode(MEAS_VOLTAGE, i);
  300. }
  301. }
  302. #endif