![[ARM] STM32_FND,DHT11](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsQkf4%2FbtsGuHLHqWm%2FGX9mITWSpq5zLSFrM8uEk1%2Fimg.png)
1. FND
- Common Cathode type
- D1 ~ D4 : Common pin → 0이면 ON, 1이면 OFF
- A ~ G : Segment pin → 1이면 해당 핀 ON
- DP : Decimal pin → 1이면 소수점 ON
(1), (2) : Prescaler : 16-1
(3) : PB0 ~ PB7 : GPIO Output(A ~ DP), PC0 ~ PC3 : GPIO Output(D1 ~ D4)
`SysTick_Handler()` : 1ms마다 실행 → `SystickCallBack()` 함수 1ms마다 실행
1-1. 2, 4번째 FND만 ON
void SystickCallBack() // Run every 1ms
{
// 2, 4번째 FND만 켜짐
static int pos = 0;
GPIOB->ODR = 0b11111111 * (pos%2); // 1ms마다 ON/OFF 반복
GPIOC->ODR = 0b1111 - (1<<pos); // 1110 -> 1101 -> 1011 -> 0111 -> ...
/*
* GPIOB=0x00 일 때, GPIOC=1110 -> 첫번째 FND OFF
* GPIOB=0xFF 일 때, GPIOC=1101 -> 두번째 FND ON
* GPIOB=0x00 일 때, GPIOC=1011 -> 세번째 FND OFF
* GPIOB=0xFF 일 때, GPIOC=0111 -> 네번째 FND ON
*/
pos++;
pos %= 4;
}
1-2. 1234 출력
uint8_t digit[4] = {
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110 // 4
};
void SystickCallBack() // Run every 1ms
{
static int pos = 0;
GPIOB->ODR = digit[pos];
GPIOC->ODR = 0b1111 - (1<<pos); // 1110 -> 1101 -> 1011 -> 0111
pos++;
pos %= 4;
}
1-3. count up
코드 ver.1
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/*
* --a--
* | |
* f b
* | |
* --g--
* | |
* e c
* | |
* --d--
*/
uint8_t font[] = {
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01100111 // 9
};
uint8_t digit[4] = {0,};
void SystickCallBack() // Run every 1ms
{
static int pos = 0;
GPIOC->ODR = 0b1111;
GPIOB->ODR = digit[pos];
GPIOC->ODR = 0b1111 - (1<<pos); // 1110 -> 1101 -> 1011 -> 0111
//
pos++;
pos %= 4;
}
/* USER CODE END 0 */
int main(void)
{
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
static int count = 0;
char str[5];
sprintf(str, "%04d", count);
for(int i = 0; i < 4; i++)
{
digit[i] = font[str[i] - 0x30];
/*
* 문자형 '1' == 0x30(ASCII) 이기때문에 숫자 1로 바꿔주기위해 -0x30
*/
}
count++;
count %= 10000;
HAL_Delay(50);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
코드 ver.2
while (1)
{
static int count = 0;
digit[0] = font[count / 1000]; // 1000의 자리
digit[1] = font[count % 1000 / 100]; // 100의 자리
digit[2] = font[count % 1000 % 100 / 10]; // 10의 자리
digit[3] = font[count % 1000 % 100 % 10]; // 1의 자리
count++;
count %= 10000;
HAL_Delay(50);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
`sprintf()` 를 사용하지 않고 ver.2와 같이 코딩하는 것이 메모리를 훨씬 적게 사용함
1-4. Ultrasonic 활용 FND 거리 출력
#include "main.h"
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/*
* --a--
* | |
* f b
* | |
* --g--
* | |
* e c
* | |
* --d--
*/
uint8_t font[] = {
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01100111 // 9
};
uint8_t digit[4] = {0,};
void SystickCallBack() // Run every 1ms
{
static int pos = 0;
GPIOC->ODR = 0b1111;
GPIOB->ODR = digit[pos];
GPIOC->ODR = 0b1111 - (1<<pos); // 1110 -> 1101 -> 1011 -> 0111
//
pos++;
pos %= 4;
}
// delay Function implement using TIMER11(for us delay)
void delayUS(uint16_t time)
{
htim11.Instance->CNT = 0;
while(htim11.Instance->CNT < time);
}
uint32_t IC_Val1 = 0;
uint32_t IC_Val2 = 0;
uint32_t Difference = 0;
uint8_t IsFirstCaptured = 0;
uint32_t Distance = 0;
// ISR function(Input Capture)
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
// If Rising edge occurs, execute the code
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
// Rising edge Interrupt
if(IsFirstCaptured == 0)
{
// Read Timer CNT
IC_Val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
IsFirstCaptured = 1;
// Next Interrupt -> Falling edge set
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1,
TIM_INPUTCHANNELPOLARITY_FALLING);
}
// Falling edge Interrupt
else if(IsFirstCaptured == 1)
{
// Read Timer CNT
IC_Val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
htim->Instance->CNT = 0;
if(IC_Val2 > IC_Val1) Difference = IC_Val2 - IC_Val1;
// (IC_Val2 - IC_Val1) mean Ultrasonic transmit and receive time difference
else if(IC_Val1 > IC_Val2) Difference = (0xffff - IC_Val1) + IC_Val2;
// (IC_Val1 > IC_Val2) mean CNT value overflow
// calculate distance
/*
* CLK = 1Mhz -> 1clk = 1us
* distance = velocity * time = 340[m] * (CNT/2)[us]) = 0.034 * CNT / 2
*/
Distance = Difference * 0.034 / 2;
// Next Interrupt -> Rising edge set
IsFirstCaptured = 0;
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1,
TIM_INPUTCHANNELPOLARITY_RISING);
// disable Interrupt
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
}
}
}
uint32_t getDistance()
{
// Trigger
HAL_GPIO_WritePin(Trigger_GPIO_Port, Trigger_Pin, 1);
delayUS(10);
HAL_GPIO_WritePin(Trigger_GPIO_Port, Trigger_Pin, 0);
// enable Interrupt -> can only occur Interrupt when I want to
__HAL_TIM_ENABLE_IT(&htim1, TIM_IT_CC1);
return Distance;
}
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start(&htim11); // for us delay
HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1); // for Ultrasonic
/* USER CODE END 2 */
/* USER CODE BEGIN WHILE */
while (1)
{
int dist = getDistance();
digit[0] = font[dist / 1000];
digit[1] = font[dist % 1000 / 100];
digit[2] = font[dist % 1000 % 100 / 10];
digit[3] = font[dist % 1000 % 100 % 10];
HAL_Delay(100);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
1-5. 일정 거리 초과하면 FND OFF + 이하면 깜빡이며 출력
#include "main.h"
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/*
* --a--
* | |
* f b
* | |
* --g--
* | |
* e c
* | |
* --d--
*/
uint8_t font[] = {
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01100111, // 9
};
uint8_t digit[4] = {0,};
void SystickCallBack() // Run every 1ms
{
static uint16_t msec = 0;
static uint8_t vpos = 0;
static uint8_t mask = 0;
msec++;
if(msec > 10)
{
msec = 0;
vpos++;
vpos %= 5;
if(vpos == 0) mask = 0xff - 0b11111110; // a segment ON
if(vpos == 1) mask = 0xff - 0b11011101; // b,f segment ON
if(vpos == 2) mask = 0xff - 0b10111111; // g segment ON
if(vpos == 3) mask = 0xff - 0b11101011; // c,e segment ON
if(vpos == 4) mask = 0xff - 0b11110111; // d segment ON
}
static int pos = 0;
GPIOC->ODR = 0b1111;
GPIOB->ODR = digit[pos] & mask;
GPIOC->ODR = 0b1111 - (1<<pos); // 1110 -> 1101 -> 1011 -> 0111
pos++;
pos %= 4;
}
// delay Function implement using TIMER11(for us delay)
void delayUS(uint16_t time)
{
htim11.Instance->CNT = 0;
while(htim11.Instance->CNT < time);
}
uint32_t IC_Val1 = 0;
uint32_t IC_Val2 = 0;
uint32_t Difference = 0;
uint8_t IsFirstCaptured = 0;
uint32_t Distance = 0;
// ISR function(Input Capture)
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
// If Rising edge occurs, execute the code
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
// Rising edge Interrupt
if(IsFirstCaptured == 0)
{
// Read Timer CNT
IC_Val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
IsFirstCaptured = 1;
// Next Interrupt -> Falling edge set
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1,
TIM_INPUTCHANNELPOLARITY_FALLING);
}
// Falling edge Interrupt
else if(IsFirstCaptured == 1)
{
// Read Timer CNT
IC_Val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
htim->Instance->CNT = 0;
if(IC_Val2 > IC_Val1) Difference = IC_Val2 - IC_Val1;
// (IC_Val2 - IC_Val1) mean Ultrasonic transmit and receive time difference
else if(IC_Val1 > IC_Val2) Difference = (0xffff - IC_Val1) + IC_Val2;
// (IC_Val1 > IC_Val2) mean CNT value overflow
// calculate distance
/*
* CLK = 1Mhz -> 1clk = 1us
* distance = velocity * time = 340[m] * (CNT/2)[us]) = 0.034 * CNT / 2
*/
Distance = Difference * 0.34 / 2;
// Next Interrupt -> Rising edge set
IsFirstCaptured = 0;
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1,
TIM_INPUTCHANNELPOLARITY_RISING);
// disable Interrupt
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
}
}
}
uint32_t getDistance()
{
// Trigger
HAL_GPIO_WritePin(Trigger_GPIO_Port, Trigger_Pin, 1);
delayUS(10);
HAL_GPIO_WritePin(Trigger_GPIO_Port, Trigger_Pin, 0);
// enable Interrupt -> can only occur Interrupt when I want to
__HAL_TIM_ENABLE_IT(&htim1, TIM_IT_CC1);
return Distance;
}
/* USER CODE END 0 */
int main(void)
{
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
int dist = getDistance();
if(dist < 500)
{
digit[0] = font[dist / 1000];
digit[1] = font[dist % 1000 / 100];
digit[2] = font[dist % 1000 % 100 / 10];
digit[3] = font[dist % 1000 % 100 % 10];
}
else
{
memset(digit, 0, 4);
}
HAL_Delay(1);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
코드 리뷰
void SystickCallBack() // Run every 1ms
{
static uint16_t msec = 0;
static uint8_t vpos = 0;
static uint8_t mask = 0;
msec++;
if(msec > 10)
{
msec = 0;
vpos++;
vpos %= 5;
if(vpos == 0) mask = 0xff - 0b11111110; // a segment ON
if(vpos == 1) mask = 0xff - 0b11011101; // b,f segment ON
if(vpos == 2) mask = 0xff - 0b10111111; // g segment ON
if(vpos == 3) mask = 0xff - 0b11101011; // c,e segment ON
if(vpos == 4) mask = 0xff - 0b11110111; // d segment ON
}
static int pos = 0;
GPIOC->ODR = 0b1111;
GPIOB->ODR = digit[pos] & mask;
GPIOC->ODR = 0b1111 - (1<<pos); // 1110 -> 1101 -> 1011 -> 0111
pos++;
pos %= 4;
}
...
int main(void)
{
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
int dist = getDistance();
if(dist < 500)
{
digit[0] = font[dist / 1000];
digit[1] = font[dist % 1000 / 100];
digit[2] = font[dist % 1000 % 100 / 10];
digit[3] = font[dist % 1000 % 100 % 10];
}
else
{
memset(digit, 0, 4);
}
HAL_Delay(1);
- while문에서 Ultrasonic으로부터 거리를 받아옴 → 거리가 500mm미만이 되면 FND출력, 이상이면 FND OFF
- 500mm미만일 때 거리 4자리수를 `digit[]`배열에 저장 → `SystickCallBack()` 함수에서 배열의 값을 ODR에 저장하여 FND 출력
- `SystickCallBack()` : 1ms 마다 실행 → 1ms마다 msec++
- `if(msec > 10)` : 10ms마다 실행되며 실행될 때마다 특정 segment bit만 1로 하는 mask 데이터 저장
- `digit[pos] & mask` : 0~9를 표시하는 `digit[]` 배열의 값을 masking하여 특정 segment만 출력
- ex) digit[0]=0b01100111(숫자 9표시) 일때 a segment 출력 → b,f segment 출력 → …
- 위 코드에서는 if문 실행 주기가 너무 길어서 FND 출력이 잘 안보임
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
...
Distance = Difference * 0.34 / 2;
...
}
0.34 : mm 단위
0.034 : cm 단위
2. DHT11
: 온습도 센서
- 40bit data 전송
: 습도 정수 8bit + 습도 소수 8bit + 온도 정수 8bit + 온도 소수 8bit + 합 8bit(parity bit)
- 반이중통신
: Data Single bus → 송수신 동시 불가
Timing Diagram 전체 흐름
- MCU → DHT11 > Start signal (DHT11 : LOW power mode → RUN mode)
- DHT11 → MCU > 온/습도 data 포함한 40bit 전송
- DHT11 40bit 전송 후 LOW power mode
Timing Diagram 세부 흐름
- Cycle Process : [Start Signal to DHT] → [Response to MCU] → [Data send to MCU]
[Start Signal to DHT] : MCU가 DHT에 “data를 받아들일 준비가 되었다” 라는 신호를 보냄
1. Free status : MCU → DH11 > HIGH 유지
2. MCU → DHT11 > LOW signal 18ms 유지
3. MCU → DHT11 > HIGH signal 주고 DHT11 20~40us 응답대기
[Response to MCU] : DHC가 MCU에 “data를 보내겠다” 라는 신호를 보냄
4. DHT11 → MCU > LOW 80us → HIGH 80us
[Data send to MCU] : DHC가 MCU에 40bit의 data를 보냄 → GPIO PIN bit로 data 읽을 수 있음
5. DHT11 → MCU > 데이터 전송
a. data 0 : LOW 50us → HIGH 26~28us
b. data 1 : LOW 50us → HIGH 70us
⇒ HIGH 유지 시간에 따라 해당 데이터가 ‘0’ or ‘1’ Check
6. 5번 과정 40번 반복(40bit 데이터 전송)
7. DHT11 40bit 전송 후 LOW power mode
⇒ 1 cycle : about 4ms
→ Sampling Period : 1s
GPIO pin 1개로 Input, Output mode 변경하는법
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, D0_Pin|D1_Pin|D2_Pin|D3_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, SA_Pin|SB_Pin|SC_Pin|SD_Pin
|SE_Pin|SF_Pin|SG_Pin|SDP_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(Trigger_GPIO_Port, Trigger_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : D0_Pin D1_Pin D2_Pin D3_Pin */
GPIO_InitStruct.Pin = D0_Pin|D1_Pin|D2_Pin|D3_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pin : PA0 */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : SA_Pin SB_Pin SC_Pin SD_Pin
SE_Pin SF_Pin SG_Pin SDP_Pin */
GPIO_InitStruct.Pin = SA_Pin|SB_Pin|SC_Pin|SD_Pin
|SE_Pin|SF_Pin|SG_Pin|SDP_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pin : Trigger_Pin */
GPIO_InitStruct.Pin = Trigger_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(Trigger_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
ioc에서 설정하면 자동으로 생성되는 초기화 함수
→ GPIO Input 설정을 Output 설정으로 바꿀 수 있다.
2-1. 온습도 FND 출력 + 거리에 따라 FND 깜빡이는 주기 조절
/* USER CODE BEGIN 0 */
//--------------------FND code--------------------------
/*
* --a--
* | |
* f b
* | |
* --g--
* | |
* e c
* | |
* --d--
*/
uint8_t font[] = {
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01100111, // 9
};
uint8_t digit[4] = {0,};
int ftime = 20;
void SystickCallBack() // Run every 1ms
{
static uint16_t msec = 0;
static uint8_t vpos = 0;
static uint8_t mask = 0;
msec++;
if(msec > ftime)
{
msec = 0;
vpos++;
vpos %= 5;
if(vpos == 0) mask = 0xff - 0b11111110; // a segment ON
if(vpos == 1) mask = 0xff - 0b11011101; // b,f segment ON
if(vpos == 2) mask = 0xff - 0b10111111; // g segment ON
if(vpos == 3) mask = 0xff - 0b11101011; // c,e segment ON
if(vpos == 4) mask = 0xff - 0b11110111; // d segment ON
}
static int pos = 0;
GPIOC->ODR = 0b1111;
GPIOB->ODR = digit[pos] & mask;
GPIOC->ODR = 0b1111 - (1<<pos); // 1110 -> 1101 -> 1011 -> 0111
pos++;
pos %= 4;
}
// -------------------Ultrasonic code-----------------------------
// delay Function implement using TIMER11(for us delay)
void delayUS(uint16_t time)
{
htim11.Instance->CNT = 0;
while(htim11.Instance->CNT < time);
}
uint32_t IC_Val1 = 0;
uint32_t IC_Val2 = 0;
uint32_t Difference = 0;
uint8_t IsFirstCaptured = 0;
uint32_t Distance = 0;
// ISR function(Input Capture)
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
// If Rising edge occurs, execute the code
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
// Rising edge Interrupt
if(IsFirstCaptured == 0)
{
// Read Timer CNT
IC_Val1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
IsFirstCaptured = 1;
// Next Interrupt -> Falling edge set
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1,
TIM_INPUTCHANNELPOLARITY_FALLING);
}
// Falling edge Interrupt
else if(IsFirstCaptured == 1)
{
// Read Timer CNT
IC_Val2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
htim->Instance->CNT = 0;
if(IC_Val2 > IC_Val1) Difference = IC_Val2 - IC_Val1;
// (IC_Val2 - IC_Val1) mean Ultrasonic transmit and receive time difference
else if(IC_Val1 > IC_Val2) Difference = (0xffff - IC_Val1) + IC_Val2;
// (IC_Val1 > IC_Val2) mean CNT value overflow
// calculate distance
/*
* CLK = 1Mhz -> 1clk = 1us
* distance = velocity * time = 340[m] * (CNT/2)[us]) = 0.034 * CNT / 2
*/
Distance = Difference * 0.34 / 2;
// Next Interrupt -> Rising edge set
IsFirstCaptured = 0;
__HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1,
TIM_INPUTCHANNELPOLARITY_RISING);
// disable Interrupt
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
}
}
}
uint32_t getDistance()
{
// Trigger
HAL_GPIO_WritePin(Trigger_GPIO_Port, Trigger_Pin, 1);
delayUS(10);
HAL_GPIO_WritePin(Trigger_GPIO_Port, Trigger_Pin, 0);
// enable Interrupt -> can only occur Interrupt when I want to
__HAL_TIM_ENABLE_IT(&htim1, TIM_IT_CC1);
return Distance;
}
//------------------------DHT11 code----------------------------
int Temperature = 0;
int Humidity = 0;
typedef struct{
uint8_t Temperature;
uint8_t Humidity;
}DHT11_t;
int wait_pulse(int state)
{
__HAL_TIM_SET_COUNTER(&htim11, 0);
// same with htim11.Instance->CNT = 0;
while(HAL_GPIO_ReadPin(DHT11_GPIO_Port, DHT11_Pin) != state)
{
/*
* 100us 동안 Pin의 상태를 읽고 Pin data == state가 되면 반복문을 종료하고 1반환
* 100us가 지나도 Pin data의 상태가 변하지 않고 Pin data != state 라면 0반환
*/
if(__HAL_TIM_GetCounter(&htim11) >= 100)
return 0;
}
return 1;
}
DHT11_t DHT11_read()
{
DHT11_t result;
// -----send start signal
// change pin mode output
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = DHT11_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // set push-pull logic
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(DHT11_GPIO_Port, &GPIO_InitStruct);
// Low 18ms, High 20us
HAL_GPIO_WritePin(DHT11_GPIO_Port, DHT11_Pin, 0);
HAL_Delay(18);
HAL_GPIO_WritePin(DHT11_GPIO_Port, DHT11_Pin, 1);
delayUS(20);
// change pin mode input
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(DHT11_GPIO_Port, &GPIO_InitStruct);
// -----check answer DHT11
delayUS(40);
if(!HAL_GPIO_ReadPin(DHT11_GPIO_Port, DHT11_Pin)) // if Pin==0, execute the code
{
delayUS(80);
if(!HAL_GPIO_ReadPin(DHT11_GPIO_Port, DHT11_Pin)) // timeout
// if High after 80us wait == Normal signal, Low == error
return;
}
if(wait_pulse(GPIO_PIN_RESET) == 0)
/*
* Pin data == reset(=0) 이면 1 반환
* Pin data != reset 이면 100us 딜레이 후 0 반환
* => Pin data != 0 이면 리턴
*/
return;
// -----read data
uint8_t out[5], i, j;
for(i = 0; i < 5; i++)
// humidity integral, decimal,
// temperature integral, decimal, check sum => 5byte
{
for(j = 0; j < 8; j++) // 8bit
{
if(!wait_pulse(GPIO_PIN_SET)) // Pin data != 1 이면 리턴
return;
delayUS(40);
if(!HAL_GPIO_ReadPin(DHT11_GPIO_Port, DHT11_Pin))
out[i] &= ~(1<<(7-j)); // state 0
else
out[i] |= (1<<(7-j)); // state 1
if(!wait_pulse(GPIO_PIN_RESET)) // wait for next bit
return;
}
}
// -----compare check sum
if(out[4] != (out[0] + out[1] + out[2] + out[3]))
return;
result.Temperature = out[2];
result.Humidity = out[0];
return result;
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start(&htim11); // for us delay
HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1); // for Ultrasonic
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
ftime = getDistance()/100;
// 거리에 따라 FND 깜빡이는 주기 조절(거리 가까우면 주기 ↓, 계속 출력되는 것처러 보임)
DHT11_t DHT11Value = DHT11_read();
digit[0] = font[DHT11Value.Temperature / 10];
digit[1] = font[DHT11Value.Temperature % 10];
digit[2] = font[DHT11Value.Humidity / 10];
digit[3] = font[DHT11Value.Humidity % 10];
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
Made By Minseok KIM
'ARM > 1_Study' 카테고리의 다른 글
[ARM] I2C Level Shifter (0) | 2024.04.10 |
---|---|
[ARM] STM32_RTC, Switch (0) | 2024.04.02 |
[ARM] STM32_LCD I2C, ADC(polling 방식, DMA 방식), CDS (0) | 2024.03.29 |
[ARM] STM32_Radar (0) | 2024.03.24 |
[ARM] STM32_Buzzer, Ulatrasonic, 필터링, ServoMotor (0) | 2024.03.19 |
Let's Be Happy!
도움이 되었으면 좋겠어요 :)