diff --git a/Core/Inc/external_temp.h b/Core/Inc/external_temp.h new file mode 100644 index 0000000..3ee5e6e --- /dev/null +++ b/Core/Inc/external_temp.h @@ -0,0 +1,11 @@ +#ifndef __EXTERNAL_TEMP +#define __EXTERNAL_TEMP + +extern ADC_HandleTypeDef hadc1; + + + +void external_temp_show_celsius(void); +void external_temp_show_fahrenheit(void); + +#endif diff --git a/Core/Inc/generic_macros.h b/Core/Inc/generic_macros.h new file mode 100644 index 0000000..b864600 --- /dev/null +++ b/Core/Inc/generic_macros.h @@ -0,0 +1,10 @@ +#ifndef __GENERIC_MACROS +#define __GENERIC_MACROS + +#define PANIC(status) \ + do { \ + GPIOD->ODR = status; \ + while (1) {} \ + } while (0) + +#endif diff --git a/Core/Inc/lcd.h b/Core/Inc/lcd.h new file mode 100644 index 0000000..1082aca --- /dev/null +++ b/Core/Inc/lcd.h @@ -0,0 +1,24 @@ +#ifndef __LCD +#define __LCD + +#define DISPLAY_RS ((uint16_t) (0x1U << 7)) +#define DISPLAY_RW ((uint16_t) (0x1U << 10)) +#define DISPLAY_ENA ((uint16_t) (0x1U << 11)) + +#define DISPLAY_POLL_UNTIL_READY do { while (display_read_status() & 0x80) {} } while (0) + +#define DISPLAY_SET_INCREMENT do { display_write_instruction_byte(0x06); } while (0) +#define DISPLAY_SET_DECREMENT do { display_write_instruction_byte(0x04); } while (0) + +#define DISPLAY_SET_CURSOR(line, position) do { display_write_instruction_byte(0x80 | (line << 6) | position); } while (0) + +#define DISPLAY_CLEAR do { display_write_instruction_byte(0x01); } while (0) + + +void display_init(void); +uint8_t display_read_status(void); +void display_write_instruction_byte(uint8_t code); +void display_write_data_byte(uint8_t code); +void display_write_data_seq(char *codes); + +#endif diff --git a/Core/Src/external-temperature.c b/Core/Src/external-temperature.c new file mode 100644 index 0000000..e69de29 diff --git a/Core/Src/external_temp.c b/Core/Src/external_temp.c new file mode 100644 index 0000000..e9cc7c1 --- /dev/null +++ b/Core/Src/external_temp.c @@ -0,0 +1,98 @@ +#include "main.h" +#include "generic_macros.h" +#include "lcd.h" +#include "external_temp.h" + +static uint32_t external_temp_read(void) +{ + HAL_ADC_Start(&hadc1); + if (HAL_ADC_PollForConversion(&hadc1, 100) != HAL_OK) + PANIC(0x4000); + + return HAL_ADC_GetValue(&hadc1); +} + +static int external_temp_convert_to_celsius(uint32_t value) +{ + return (2512 - value) << 2; +} + +static int external_temp_convert_to_fahrenheit(uint32_t value) +{ + return (2953 - value) * 50 / 7; +} + +static void external_temp_print(int temperature) +{ + int add_sign = temperature < 0; + if (add_sign) + temperature = ~(temperature - 1); // if value is not positive, the string conversion will break + + int temp1 = temperature; + + for (int i = 0; i < 2; i++) { + temperature /= 10; + display_write_data_byte('0' + (char) (temp1 - temperature * 10)); + temp1 = temperature; + } + + display_write_data_byte('.'); + + for (int i = 0; i < 3; i++) { + temperature /= 10; + display_write_data_byte('0' + (char) (temp1 - temperature * 10)); + temp1 = temperature; + + if (temp1 == 0) { + display_write_data_seq(" "); + break; + } + } + + if (add_sign) { + DISPLAY_SET_CURSOR(1, 0); + display_write_data_byte('-'); + } +} + +static void external_temp_print_celsius(int temperature) +{ + DISPLAY_SET_CURSOR(1, 7); + DISPLAY_SET_DECREMENT; + display_write_data_seq("C "); + + external_temp_print(temperature); +} + +static void external_temp_print_fahrenheit(int temperature) +{ + DISPLAY_SET_CURSOR(1, 7); + DISPLAY_SET_DECREMENT; + display_write_data_seq("F "); + + external_temp_print(temperature); +} + +void external_temp_show_celsius(void) +{ + DISPLAY_CLEAR; + DISPLAY_SET_INCREMENT; + + display_write_data_seq("Temperature"); + + uint32_t value = external_temp_read(); + int temp = external_temp_convert_to_celsius(value); + external_temp_print_celsius(temp); +} + +void external_temp_show_fahrenheit(void) +{ + DISPLAY_CLEAR; + DISPLAY_SET_INCREMENT; + + display_write_data_seq("Temperature"); + + uint32_t value = external_temp_read(); + int temp = external_temp_convert_to_fahrenheit(value); + external_temp_print_fahrenheit(temp); +} diff --git a/Core/Src/lcd.c b/Core/Src/lcd.c new file mode 100644 index 0000000..3aebda7 --- /dev/null +++ b/Core/Src/lcd.c @@ -0,0 +1,92 @@ +#include "main.h" +#include "lcd.h" +#include "generic_macros.h" + +void display_init(void) +{ + // switch to 4-bit 2-line mode + display_write_instruction_byte(0x28); + + // clear display + display_write_instruction_byte(0x01); + + // enable display + display_write_instruction_byte(0x0C); + + // move cursor to first line + display_write_instruction_byte(0x80); +} + +uint8_t display_read_status(void) +{ + // make sure GPIOE is in correct mode + GPIOE->MODER = 0x00504000; + + if (GPIOE->MODER != 0x00504000) + PANIC(0x4000); + + uint8_t status = 0; + + GPIOE->ODR = 0x0; + GPIOE->BSRR = DISPLAY_RW; + + GPIOE->BSRR = DISPLAY_ENA; + status |= (GPIOE->IDR & 0xF000) >> 8; + GPIOE->BSRR = (DISPLAY_ENA << 16); + + GPIOE->BSRR = DISPLAY_ENA; + status |= (GPIOE->IDR & 0xF000) >> 12; + GPIOE->BSRR = (DISPLAY_ENA << 16); + + GPIOE->ODR = 0x0; + + return status; +} + +void display_write_instruction_byte(uint8_t code) +{ + DISPLAY_POLL_UNTIL_READY; + + // make sure GPIOE is in correct mode + GPIOE->MODER = 0x55504000; + + if (GPIOE->MODER != 0x55504000) + PANIC(0x4000); + + GPIOE->ODR = (code & 0xF0) << 8; + GPIOE->BSRR = DISPLAY_ENA; + GPIOE->BSRR = (DISPLAY_ENA << 16); + + GPIOE->ODR = (code & 0x0F) << 12; + GPIOE->BSRR = DISPLAY_ENA; + GPIOE->BSRR = (DISPLAY_ENA << 16); +} + +void display_write_data_byte(uint8_t code) +{ + DISPLAY_POLL_UNTIL_READY; + + // make sure GPIOE is in correct mode + GPIOE->MODER = 0x55504000; + + if (GPIOE->MODER != 0x55504000) + PANIC(0x4000); + + GPIOE->ODR = ((code & 0xF0) << 8) | (DISPLAY_RS); + GPIOE->BSRR = DISPLAY_ENA; + GPIOE->BSRR = DISPLAY_ENA << 16; + + GPIOE->ODR = ((code & 0x0F) << 12) | (DISPLAY_RS); + GPIOE->BSRR = DISPLAY_ENA; + GPIOE->BSRR = DISPLAY_ENA << 16; +} + +void display_write_data_seq(char *codes) +{ + for (size_t i = 0; i < 16; i++) { + if (codes[i] != 0) + display_write_data_byte(codes[i]); + else + break; + } +} diff --git a/Core/Src/main.c b/Core/Src/main.c index 1162e63..9aaa192 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -22,6 +22,10 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ +#include "generic_macros.h" +#include "lcd.h" +#include "external_temp.h" + /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -32,18 +36,6 @@ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ -#define DISPLAY_RS ((uint16_t) (0x1U << 7)) -#define DISPLAY_RW ((uint16_t) (0x1U << 10)) -#define DISPLAY_ENA ((uint16_t) (0x1U << 11)) - -#define PANIC(status) \ - do { \ - GPIOD->ODR = status; \ - while (1) {} \ - } while (0) - -#define POLL_UNTIL_READY do { while (read_status() & 0x80) {} } while (0) - /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ @@ -52,16 +44,23 @@ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ +ADC_HandleTypeDef hadc1; /* USER CODE BEGIN PV */ -int change = 1; +void ((*executors[])(void)) = { + external_temp_show_celsius, + external_temp_show_fahrenheit +}; + +int current_executor_id = 0; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); +static void MX_ADC1_Init(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ @@ -69,70 +68,6 @@ static void MX_GPIO_Init(void); /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ -uint8_t read_status(void) -{ - // make sure GPIOE is in correct mode - GPIOE->MODER = 0x00504000; - - if (GPIOE->MODER != 0x00504000) - PANIC(0x4000); - - uint8_t status = 0; - - GPIOE->ODR = 0x0; - GPIOE->BSRR = DISPLAY_RW; - - GPIOE->BSRR = DISPLAY_ENA; - status |= (GPIOE->IDR & 0xF000) >> 8; - GPIOE->BSRR = (DISPLAY_ENA << 16); - - GPIOE->BSRR = DISPLAY_ENA; - status |= (GPIOE->IDR & 0xF000) >> 12; - GPIOE->BSRR = (DISPLAY_ENA << 16); - - GPIOE->ODR = 0x0; - - return status; -} - -void write_instruction_byte(uint8_t code) -{ - POLL_UNTIL_READY; - - // make sure GPIOE is in correct mode - GPIOE->MODER = 0x55504000; - - if (GPIOE->MODER != 0x55504000) - PANIC(0x4000); - - GPIOE->ODR = (code & 0xF0) << 8; - GPIOE->BSRR = DISPLAY_ENA; - GPIOE->BSRR = (DISPLAY_ENA << 16); - - GPIOE->ODR = (code & 0x0F) << 12; - GPIOE->BSRR = DISPLAY_ENA; - GPIOE->BSRR = (DISPLAY_ENA << 16); -} - -void write_data_byte(uint8_t code) -{ - POLL_UNTIL_READY; - - // make sure GPIOE is in correct mode - GPIOE->MODER = 0x55504000; - - if (GPIOE->MODER != 0x55504000) - PANIC(0x4000); - - GPIOE->ODR = ((code & 0xF0) << 8) | (DISPLAY_RS); - GPIOE->BSRR = DISPLAY_ENA; - GPIOE->BSRR = DISPLAY_ENA << 16; - - GPIOE->ODR = ((code & 0x0F) << 12) | (DISPLAY_RS); - GPIOE->BSRR = DISPLAY_ENA; - GPIOE->BSRR = DISPLAY_ENA << 16; -} - /* USER CODE END 0 */ /** @@ -164,67 +99,21 @@ int main(void) /* Initialize all configured peripherals */ MX_GPIO_Init(); + MX_ADC1_Init(); /* USER CODE BEGIN 2 */ GPIOD->ODR = 0xF000; - - // switch to 4-bit 2-line mode - write_instruction_byte(0x28); - - // reset display - write_instruction_byte(0x01); - - // enable display - write_instruction_byte(0x0C); - - // move cursor to first line - write_instruction_byte(0x80); - - // write string - char a[] = "Well, hi there!"; - for (int i = 0; i < sizeof(a)-1; i++) { - write_data_byte(a[i]); - } - - /* - // move cursor to second line - write_instruction_byte(0xC0); - while (read_status() & 0x80) {} - - // write another string - char b[] = "I'm doing it!"; - for (int i = 0; i < sizeof(b)-1; i++) { - write_data_byte(b[i]); - while (read_status() & 0x80) {} - } - */ - + display_init(); GPIOD->ODR = 0x0000; - unsigned int counter = 0; - write_instruction_byte(0x04); // set address decrement after write - /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { - counter += change; - counter &= 0xFFFF; - - unsigned int c = counter; - - write_instruction_byte(0xC4); - - for (int i = 0; i < 5; i++) { - int current_digit = c % 10; - c /= 10; - - write_data_byte('0' + (char) current_digit); - } - - HAL_Delay(10); + executors[current_executor_id](); + HAL_Delay(250); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ @@ -273,6 +162,58 @@ void SystemClock_Config(void) } } +/** + * @brief ADC1 Initialization Function + * @param None + * @retval None + */ +static void MX_ADC1_Init(void) +{ + + /* USER CODE BEGIN ADC1_Init 0 */ + + /* USER CODE END ADC1_Init 0 */ + + ADC_ChannelConfTypeDef sConfig = {0}; + + /* USER CODE BEGIN ADC1_Init 1 */ + + /* USER CODE END ADC1_Init 1 */ + + /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) + */ + hadc1.Instance = ADC1; + hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; + hadc1.Init.Resolution = ADC_RESOLUTION_12B; + hadc1.Init.ScanConvMode = DISABLE; + hadc1.Init.ContinuousConvMode = DISABLE; + hadc1.Init.DiscontinuousConvMode = DISABLE; + hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; + hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc1.Init.NbrOfConversion = 1; + hadc1.Init.DMAContinuousRequests = DISABLE; + hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; + if (HAL_ADC_Init(&hadc1) != HAL_OK) + { + Error_Handler(); + } + + /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. + */ + sConfig.Channel = ADC_CHANNEL_9; + sConfig.Rank = 1; + sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; + if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN ADC1_Init 2 */ + + /* USER CODE END ADC1_Init 2 */ + +} + /** * @brief GPIO Initialization Function * @param None @@ -286,6 +227,7 @@ static void MX_GPIO_Init(void) /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); diff --git a/Core/Src/stm32f4xx_it.c b/Core/Src/stm32f4xx_it.c index 106db94..3f23040 100644 --- a/Core/Src/stm32f4xx_it.c +++ b/Core/Src/stm32f4xx_it.c @@ -41,7 +41,9 @@ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ -extern int change; +extern void ((*executors[])(void)); +extern void *current_executor(void); +extern int current_executor_id; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ @@ -205,9 +207,15 @@ void EXTI0_IRQHandler(void) { /* USER CODE BEGIN EXTI0_IRQn 0 */ - change *= -1; + GPIOD->ODR = 0x1000; + + current_executor_id += 1; + current_executor_id &= 1; + + for (int i = 900000; i > 0; i--) asm("nop"); + + GPIOD->ODR = 0x0000; - for (int i = 0; i < 400000; i++) {asm("nop");} /* USER CODE END EXTI0_IRQn 0 */ HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); /* USER CODE BEGIN EXTI0_IRQn 1 */