add external temperature sensor support, allow to cycle through different test modes
This commit is contained in:
parent
2bcf89efe1
commit
47733fdae4
|
@ -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
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef __GENERIC_MACROS
|
||||
#define __GENERIC_MACROS
|
||||
|
||||
#define PANIC(status) \
|
||||
do { \
|
||||
GPIOD->ODR = status; \
|
||||
while (1) {} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
196
Core/Src/main.c
196
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();
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue