.. _program_listing_file_mainboard_Src_peripherals_si8900.c: Program Listing for File si8900.c ================================= |exhale_lsh| :ref:`Return to documentation for file ` (``mainboard/Src/peripherals/si8900.c``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #include "peripherals/si8900.h" #include "error/error.h" #include "mainboard_config.h" #include "usart.h" #include #include bool si8900_ready = false; bool si8900_init(UART_HandleTypeDef *huart, GPIO_TypeDef *reset_gpio, uint16_t reset_pin) { uint8_t recv = 0; uint8_t tx = 0xAA; bool timeout = false; bool code_receive = false; bool code_confirm = false; HAL_GPIO_WritePin(ADC_SIN_GPIO_Port, ADC_SIN_Pin, GPIO_PIN_SET); HAL_Delay(5); HAL_GPIO_WritePin(ADC_SIN_GPIO_Port, ADC_SIN_Pin, GPIO_PIN_RESET); uint32_t time = HAL_GetTick(); HAL_UART_Transmit(huart, &tx, 1, 10); while ((!code_receive || !code_confirm) && !timeout) { HAL_UART_Receive(huart, &recv, 1, 10); if (recv == 0x55) { if (code_receive) { code_confirm = true; si8900_ready = true; } code_receive = true; } else { code_receive = false; code_confirm = false; } HAL_UART_Transmit(huart, &tx, 1, 10); timeout = (HAL_GetTick() - time) >= SI8900_INIT_TIMEOUT; } if (timeout) { error_set(ERROR_ADC_INIT, 0, HAL_GetTick()); return false; } error_reset(ERROR_ADC_INIT, 0); return true; } bool si8900_read_channel(UART_HandleTypeDef *huart, SI8900_CHANNEL ch, uint16_t *voltage) { if (si8900_ready) { uint8_t conf = si8900_cnfg_0 | (ch << 4); HAL_UART_Transmit(huart, &conf, 1, 1); uint8_t recv, count = 0; while (recv != conf) { HAL_UART_Receive(huart, &recv, 1, 1); if (count++ > 5) { error_set(ERROR_ADC_TIMEOUT, 0, HAL_GetTick()); return false; } } uint8_t data[2] = {0}; HAL_UART_Receive(huart, data, 2, 1); *voltage = si8900_convert_voltage(data); error_reset(ERROR_ADC_TIMEOUT, 0); return true; } return false; } uint16_t si8900_convert_voltage(uint8_t adc_hl[2]) { // MSB | LSB uint16_t dig = ((adc_hl[0] & 0b00001111) << 6) | ((adc_hl[1] & 0b01111110) >> 1); return ((SI8900_VREF * (float)dig) / 1024) * 100; }