![[ARM] STM32_Driver(CLCD I2C, Ultrasonic)](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5ht3o%2FbtsGVhHjafC%2FWGQhXngDZ79ZAGOskeTD6k%2Fimg.png)
1. CLCD I2C



1-1. CLCD 메모리
- CGROM(Character Generator ROM)
- 8비트 문자 패턴을 저장하고 있는 메모리
- 208개의 5x8 도트와 32개의 5x10 도트의 문자 패턴 저장(9920bit)
- Character Code 0b0010 0000(공백) ~ 0b0111 1111(←)까지는 ASCII (아스키 코드) 와 일치
→ c언어에서 문자로 표현된 데이터를 변환하지 않고 그대로 LCD에 출력 가능

→ 위 표와 같이 문자가 CGROM에 저장되어 있고 저장된 문자를 DDRAM을 통해 화면에 출력
→ 표 좌측 CGRAM(1) ~ CGRAM(8)은 사용자가 문자를 만들어 CGRAM에 저장하여 사용 가능
- CGRAM(Character Generator RAM)
- 사용자 정의 문자를 저장하는 메모리
- 6bit Address
- 8개의 5×8 도트 혹은 4개의 5×10 도트의 문자 패턴 저장 가능(1개 문자당 8byte이기때문에 메모리 크기 : 64byte)
- Character Code 0b0000 0000 ~ 0b0000 1111일 때 CGRAM에 저장된 사용자 정의 문자를 출력 가능

→ 위 표와 같이 CGRAM Address 0b00 0000 ~ 0b00 0111 8개의 주소(LCD블록 하나의 세로 길이 = 8)가 하나의 Charatcer Code
- DDRAM(Display Data RAM)
- LCD 화면에 표시되는 실제 데이터가 저장되는 메모리
- 80개의 문자 저장(1x80byte)
- 1행 주소 : 0x00 ~ 0x27, 2행 주소 : 0x40 ~ 0x67


→ 위 표와 같이 DDRAM에 저장할 수 있는 문자는 80개이지만 LCD Display가 16x2이기 때문에 32개의 문자만 출력
(나머지 문자는 저장되어 있지만 보이지 않는 것이기 때문에 display shift하면 볼 수 있다.)
▶ LCD 모듈은 Character Code를 통해 메모리에 저장된 문자를 LCD에 표시한다.
1-2. CLCD Register
- IR(Instruction Register)
- LCD 모듈을 제어하기 위한 명령을 보관하고 있는 레지스터
- 제어에 필요한 명령 저장 및 DDRAM 위치 주소와 CGRAM 위치 주소 정보 저장
- DR(Data Register)
- DDRAM, CGRAM에 write/read할 데이터를 임시로 저장

RS : 레지스터 선택
RW : Read/Write
1-3. 기타
- AC(Address Counter)
- DDRAM, CGRAM 주소 할당
- 명령어의 주소가 IR에 저장 → 주소 정보가 IR에서 AC로 전송 → 메모리 write/read → AC(메모리 주소) 1 증가/감소
- RS = 0, R/W = 1일 때 AC 내용이 DB0~DB6으로 출력
- BF(Busy Flag)
- BF = 1이면, 모듈은 내부 동작 모드 → 다음 명령 불가
- RS = 0, R/W = 1이면, BF 데이터가 DB7로 출력
1-4. CLCD Driver


Data 전송 분석

- data 상위 4bit + control bit 4bit
- data 하위 4bit + control bit 4bit
⇒ 1Byte data를 상위 4bit, 하위 4bit로 나누어 2번 전송

PCF8574 I2C Module Address : 0010 0A2A1A0 ⇒ 0x27
RW bit 포함 ⇒ Wirte mode에서 (0x27<<1)로 전송


RS = 0) Instruction Register, =1) Data Register
RW = 0일 때, 데이터 전송


void LCD_init() // RESET FUNCTION
{
LCD_delay(15);
LCD_cmdMode();
LCD_writeMode();
LCD_sendHighNibble(0x30);
LCD_delay(5);
LCD_sendHighNibble(0x30);
LCD_delay(1);
LCD_sendHighNibble(0x30);
LCD_sendHighNibble(0x20);
LCD_sendByte(LCD_4BIT_FUNCTION_SET); // Function set 4bit interface, 2line, 5x8font
LCD_sendByte(LCD_DISPLAY_OFF); // display OFF
LCD_sendByte(LCD_DISPLAY_CLEAR); // display clear
LCD_sendByte(LCD_ENTRY_MODE_SET); // entry mode set
LCD_sendByte(LCD_DISPLAY_ON); // display ON
LCD_backLightON(); // backlight ON
}
위 datasheet를 통해서 만든 RESET FUNCTION
SDA, SCL 분석
데이터 전송 flow
START signal 전송 → Slave Address 전송(R/W포함) 8bit 전송 → ACK 수신 → Data 8bit 전송 → ACK 수신 → STOP signal 전송



- START signal : SCL High & SDA Falling edge
- STOP signal : SCL High & SDA Rising edge
- ACK signal : SCL High & SDA Low (Slave → Master 전송)
APMain.c
/*
* AP_Main.c
*
* Created on: Apr 23, 2024
* Author: k1min
*/
#include "AP_Main.h"
#include "stdio.h"
Button_t Button_1, Button_2, Button_3;
LED_t LED_1, LED_2, LED_3;
void sys_init()
{
button_init(&Button_1, GPIOC, GPIO_PIN_10);
button_init(&Button_2, GPIOC, GPIO_PIN_11);
button_init(&Button_3, GPIOC, GPIO_PIN_12);
LED_init(&LED_1, GPIOC, GPIO_PIN_8);
LED_init(&LED_2, GPIOC, GPIO_PIN_6);
LED_init(&LED_3, GPIOC, GPIO_PIN_5);
LCD_init();
}
int APMain()
{
sys_init();
LCD_writeStringXY(0, 0, "Hello STM32!");
LCD_writeStringXY(1, 0, "KCCISTC Harman");
char buff[50];
int counter = 0;
while (1)
{
sprintf(buff, "count : %d ", counter++);
LCD_writeStringXY(1, 0, buff);
HAL_Delay(500);
}
return 0;
}
CLCD Driver
// 헤더 파일
/*
* CLCD.h
*
* Created on: Apr 23, 2024
* Author: k1min
*/
#ifndef DRIVER_CLCD_CLCD_H_
#define DRIVER_CLCD_CLCD_H_
#include "stm32f4xx_hal.h"
#define LCD_RS 0
#define LCD_RW 1
#define LCD_E 2
#define LCD_BACKLIGHT 3
#define lcdDevAddr 0x27
#define lcdDevAddrRW (0x27 << 1)
#define LCD_4BIT_FUNCTION_SET 0x28
#define LCD_DISPLAY_OFF 0x08
#define LCD_DISPLAY_ON 0x0C
#define LCD_DISPLAY_CLEAR 0x01
#define LCD_ENTRY_MODE_SET 0X06
void LCD_init();
void LCD_delay(uint32_t Delay);
void LCD_backLightON();
void LCD_writeCmdData(uint8_t data);
void LCD_writeCharData(uint8_t data);
void LCD_writeString(char *str);
void LCD_gotoXY(uint8_t row, uint8_t col);
void LCD_writeStringXY(uint8_t row, uint8_t col, char *str);
void LCD_cmdMode();
void LCD_charMode();
void LCD_writeMode();
void LCD_sendByte(uint8_t data);
void LCD_sendData(uint8_t data);
void LCD_sendHighNibble(uint8_t data);
void LCD_sendLowNibble(uint8_t data);
void LCD_E_High();
void LCD_E_Low();
#endif /* DRIVER_CLCD_CLCD_H_ */
// 소스 파일
/*
* CLCD.c
*
* Created on: Apr 23, 2024
* Author: k1min
*/
#include "CLCD.h"
extern I2C_HandleTypeDef hi2c1;
uint8_t lcdData = 0;
void LCD_init() // RESET FUNCTION
{
LCD_delay(15);
LCD_cmdMode();
LCD_writeMode();
LCD_sendHighNibble(0x30);
LCD_delay(5);
LCD_sendHighNibble(0x30);
LCD_delay(1);
LCD_sendHighNibble(0x30);
LCD_sendHighNibble(0x20);
LCD_sendByte(LCD_4BIT_FUNCTION_SET); // Function set 4bit interface, 2line, 5x8font
LCD_sendByte(LCD_DISPLAY_OFF); // display OFF
LCD_sendByte(LCD_DISPLAY_CLEAR); // display clear
LCD_sendByte(LCD_ENTRY_MODE_SET); // entry mode set
LCD_sendByte(LCD_DISPLAY_ON); // display ON
LCD_backLightON(); // backlight ON
}
void LCD_delay(uint32_t Delay)
{
HAL_Delay(Delay);
}
void LCD_backLightON()
{
lcdData |= (1 << LCD_BACKLIGHT);
LCD_sendData(lcdData);
}
/*
* LCD_writeCmdData(uint8_t data), LCD_writeCharData(uint8_t data)
* => RS, RW bit setup하고 1byte 전송
*
* LCD_cmdMode(), LCD_charMode()
* => lcdData 변수의 RS 비트만 바꿔서 저장 (전송 X)
*
* LCD_writeMode()
* => lcdData 변수의 RW 비트만 바꿔서 저장 (전송 X)
*
* LCD_sendByte(uint8_t data)
* => 전송하고 싶은 data를 상위 4bit, 하위 4bit 나누어 전송
*
* LCD_sendData(uint8_t data)
* => 전송하고 싶은 data 1byte 전송(HighNibble, LowNibble 사용)
*
* LCD_sendHighNibble(uint8_t data), LCD_sendLowNibble(uint8_t data)
* => lcdData 변수의 상위 4bit를 data로 저장하고 하위 4bit를 control bit(RS,RW,E)로 저장하고 전송
*
* LCD_E_High(), LCD_E_Low()
* => lcdData 변수의 E 비트만 바꿔서 저장 (전송 X)
*
*/
void LCD_writeCmdData(uint8_t data)
{
LCD_cmdMode();
LCD_writeMode();
LCD_sendByte(data);
}
void LCD_writeCharData(uint8_t data)
{
LCD_charMode();
LCD_writeMode();
LCD_sendByte(data);
}
void LCD_writeString(char *str)
{
for (int i = 0; str[i]; i++)
{
LCD_writeCharData(str[i]);
}
}
void LCD_gotoXY(uint8_t row, uint8_t col)
{
col %= 16;
row %= 2;
uint8_t lcdRegAddr = (0x40 * row) + col;
uint8_t command = 0x80 + lcdRegAddr;
LCD_writeCmdData(command);
}
void LCD_writeStringXY(uint8_t row, uint8_t col, char *str)
{
LCD_gotoXY(row, col);
LCD_writeString(str);
}
void LCD_cmdMode()
{
lcdData &= ~(1<<LCD_RS); // RS bit set to 0 -> Instruction Register
}
void LCD_charMode()
{
lcdData |= (1<<LCD_RS); // RS bit set to 1 -> Data Register
}
void LCD_writeMode()
{
lcdData &= ~(1<<LCD_RW); // RW bit set to 0 -> write mode
}
void LCD_sendByte(uint8_t data) // Send twice upper 4 bits & lower 4 bits
{
LCD_sendHighNibble(data); // 상위 4bit 전송
LCD_sendLowNibble(data); // 하위 4bit 전송
}
void LCD_sendData(uint8_t data)
{
HAL_I2C_Master_Transmit(&hi2c1, lcdDevAddrRW, &data, 1, 1000);
// I2C 통신으로 lcdDevAddrRW 주소 1byte 전송 + data 1Byte 전송
}
void LCD_sendHighNibble(uint8_t data)
{
LCD_E_High();
lcdData = (lcdData & 0x0f) | (data & 0xf0); // 매개변수 data의 상위 4bit를 lcData의 상위 4bit로
LCD_sendData(lcdData); // MCU send data to LCD (Data Setup)
HAL_Delay(1); // for tr(pin E rise time)
LCD_E_Low();
LCD_sendData(lcdData); // MCU send data to LCD (Data Hold)
HAL_Delay(1); // for tf(pin E fall time) (Data Hold)
}
void LCD_sendLowNibble(uint8_t data)
{
LCD_E_High();
lcdData = (lcdData & 0x0f) | ((data & 0x0f) << 4); // 매개변수 data의 하위 4bit lcData의 상위 4bit로
LCD_sendData(lcdData); // MCU send data to LCD (Data Setup)
HAL_Delay(1); // for tr(pin E rise time)
LCD_E_Low();
LCD_sendData(lcdData); // MCU send data to LCD (Data Hold)
HAL_Delay(1); // for tf(pin E fall time)
}
void LCD_E_High()
{
lcdData |= (1<<LCD_E);
}
void LCD_E_Low()
{
lcdData &= ~(1<<LCD_E);
}
- 전체 코드
GitHub - k1minseok/STM32_Ultrasonic_Driver_0424
Contribute to k1minseok/STM32_Ultrasonic_Driver_0424 development by creating an account on GitHub.
github.com
2. Ultrasonic(HC-SR04)



1. 최소 10us 이상의 high level signal(Trigger)
2. 8개의 40kHz 초음파를 전송하고 펄스 신호가 돌아오는걸 감지
- 가청 주파수 : 20Hz ~ 20kHz → Ultrasonic은 사람이 들을 수 없음
3. 신호가 high level로 돌아오면 초음파의 송신부터 수신까지의 시간으로 거리 계산 가능
- 음속 : 340m/s → 음속과 초음파 전달 시간으로 거리를 구할 수 있음(거리 = 속도 * 시간)
2-1. Ultrasonic Driver



(1), (2) PC1(Echi pin) : External Interrupt mode(Rising/Falling edge) / NVIC Interrupt Enable
(3) TIM1 setup
- 주기 1us → 한 클럭(1us)당 거리 = 0.00034m = 0.034cm
(4) UART2 setup / I2C1 setup
340m:1s=x:1us
External Interrupt 실행 과정

External Interrupt setup을 하면 위 함수가 stm32f4xx_it.c
파일에 만들어짐
→ 외부 인터럽트 발생했을 떄 실행되는 함수
→ 여기서는 Rising/Falling edge 발생했을 때 실행되도록 설정

- PC1(Echo pin) Rising edge 발생 → EXTI1 실행
- Vector table의 0x0000 005C 주소로 강제 이동
- 0x0000 005C에 입력되어 있는 주소로 이동
- 해당 ISR(Interrupt Severice Routine / IRQHandler)에서 코드 실행
// 헤더 파일
/*
* Ultrasonic.h
*
* Created on: Apr 24, 2024
* Author: k1min
*/
#ifndef DRIVER_ULTRASONIC_ULTRASONIC_H_
#define DRIVER_ULTRASONIC_ULTRASONIC_H_
#include "stm32f4xx_hal.h"
void DelayInit(void);
void DelayUS(uint32_t us);
int Ultrasonic_getDistance();
void Ultrasonic_ISR_Process(uint16_t GPIO_Pin);
void Ultrasonic_clearTimer();
void Ultrasonic_startTimer();
void Ultrasonic_stopTimer();
uint16_t Ultrasonic_getTimerCounter();
int Ultrasonic_getEchopinState();
void Ultrasonic_startTrig();
int Ultrasonic_isCmpltRecvEcho();
void Ultrasonic_clearEchoFlag();
void Ultrasonic_setEchoFlag();
#endif /* DRIVER_ULTRASONIC_ULTRASONIC_H_ */
// 소스 파일
/*
* Ultrasonic.c
*
* Created on: Apr 24, 2024
* Author: k1min
*/
#include "Ultrasonic.h"
extern TIM_HandleTypeDef htim1;
uint16_t tim_counter;
int echoFlag = 0;
void DelayInit(void)
{
CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk;
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk; //~0x00000001;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; //0x00000001;
DWT->CYCCNT = 0;
/* 3 NO OPERATION instructions */
__ASM volatile ("NOP");
__ASM volatile ("NOP");
__ASM volatile ("NOP");
}
// us delay
void DelayUS(uint32_t us)
{
uint32_t cycles = (SystemCoreClock / 1000000L) * us;
uint32_t start = DWT->CYCCNT;
volatile uint32_t cnt;
do
{
cnt = DWT->CYCCNT - start;
} while (cnt < cycles);
}
int Ultrasonic_getDistance()
{
int timeout = 0;
Ultrasonic_startTrig();
while (!Ultrasonic_isCmpltRecvEcho()) // Falling edge까지 대기
{
timeout++;
if (timeout > 20) // 타임아웃 처리
return 0;
HAL_Delay(1);
}
Ultrasonic_clearEchoFlag();
return tim_counter * 0.034 / 2; //cm distance
}
void Ultrasonic_ISR_Process(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_1)
{
// Echo pin High 유지시간 측정
if (Ultrasonic_getEchopinState()) // Rising edge
{
//TIM1->CNT
Ultrasonic_clearTimer(); // TIM1 동작 전 CNT 초기화
Ultrasonic_startTimer(); // Rising edge이면 TIM1 동작 시작
Ultrasonic_clearEchoFlag();
}
else // Falling edge
{
Ultrasonic_stopTimer(); // Falling edge이면 TIM1 동작 종료
tim_counter = Ultrasonic_getTimerCounter(); // TIM1 CNT 값 읽기
Ultrasonic_setEchoFlag();
}
}
}
void Ultrasonic_clearTimer()
{
__HAL_TIM_SET_COUNTER(&htim1, 0);
}
void Ultrasonic_startTimer()
{
HAL_TIM_Base_Start(&htim1);
}
void Ultrasonic_stopTimer()
{
HAL_TIM_Base_Stop(&htim1);
}
uint16_t Ultrasonic_getTimerCounter()
{
return __HAL_TIM_GET_COUNTER(&htim1);
}
int Ultrasonic_getEchopinState()
{
return HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_1);
}
void Ultrasonic_startTrig()
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, SET);
//HAL_Delay(1);
DelayUS(15);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, RESET);
}
int Ultrasonic_isCmpltRecvEcho()
{
return echoFlag;
}
void Ultrasonic_clearEchoFlag()
{
echoFlag = 0;
}
void Ultrasonic_setEchoFlag()
{
echoFlag = 1;
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
Ultrasonic_ISR_Process(GPIO_Pin);
}
int APMain()
{
sys_init();
LCD_writeStringXY(0, 0, "Hello STM32!");
LCD_writeStringXY(1, 0, "KCCISTC Harman");
char buff[50];
int distance;
while (1)
{
if (button_getState(&Button_1) == ACT_RELEASED)
{
distance = Ultrasonic_getDistance();
if(distance > 150) distance = 150;
sprintf(buff, "dis : %dcm ", distance);
LCD_writeStringXY(1, 0, buff);
}
}
return 0;
}

위와 같이 Echo 펄스를 확인할 수 있음
1.427ms→24.259cm
범용 Ultrasonic Driver



초음파 센서 두개의 차이
- Trigger Port, Pin
- GPIOC Pin0, GPIOB Pin0
- Eho Port, Pin
- GPIOC Pin1, GPIOA, Pin4
- TIMER
- TIM1, TIM2
- Echo Flag
// 헤더 파일
/*
* Ultrasonic.h
*
* Created on: Apr 24, 2024
* Author: k1min
*/
#ifndef DRIVER_ULTRASONIC_ULTRASONIC_H_
#define DRIVER_ULTRASONIC_ULTRASONIC_H_
#include "stm32f4xx_hal.h"
// Trig Port, Trig Pin, Echo Port, Echo Pin, TIMER, Flag
typedef struct{
TIM_HandleTypeDef *TIM_handle;
GPIO_TypeDef *GPIO_Trig_Port;
uint16_t GPIO_Trig_Pin;
GPIO_TypeDef *GPIO_Echo_Port;
uint16_t GPIO_Echo_Pin;
int echoFlag;
uint16_t TIM_Counter; // distance measurement counter
}Ultrasonic_t;
void Ultraosnic_init(
Ultrasonic_t *Ultrasonic,
TIM_HandleTypeDef *TIM_handle,
GPIO_TypeDef *GPIO_Trig_Port,
uint16_t GPIO_Trig_Pin,
GPIO_TypeDef *GPIO_Echo_Port,
uint16_t GPIO_Echo_Pin);
int Ultrasonic_getDistance(Ultrasonic_t *Ultrasonic);
void Ultrasonic_ISR_Process(Ultrasonic_t *Ultrasonic, uint16_t GPIO_Pin);
void Ultrasonic_clearTimer(Ultrasonic_t *Ultrasonic);
void Ultrasonic_startTimer(Ultrasonic_t *Ultrasonic);
void Ultrasonic_stopTimer(Ultrasonic_t *Ultrasonic);
uint16_t Ultrasonic_getTimerCounter(Ultrasonic_t *Ultrasonic);
int Ultrasonic_getEchopinState(Ultrasonic_t *Ultrasonic);
void Ultrasonic_startTrig(Ultrasonic_t *Ultrasonic);
int Ultrasonic_isCmpltRecvEcho(Ultrasonic_t *Ultrasonic);
void Ultrasonic_clearEchoFlag(Ultrasonic_t *Ultrasonic);
void Ultrasonic_setEchoFlag(Ultrasonic_t *Ultrasonic);
#endif /* DRIVER_ULTRASONIC_ULTRASONIC_H_ */
// 소스 파일
/*
* Ultrasonic.c
*
* Created on: Apr 24, 2024
* Author: k1min
*/
#include "Ultrasonic.h"
#include "../Common/delayUS/delayUS.h"
void Ultraosnic_init(
Ultrasonic_t *Ultrasonic,
TIM_HandleTypeDef *TIM_handle,
GPIO_TypeDef *GPIO_Trig_Port,
uint16_t GPIO_Trig_Pin,
GPIO_TypeDef *GPIO_Echo_Port,
uint16_t GPIO_Echo_Pin)
{
Ultrasonic->TIM_handle = TIM_handle;
Ultrasonic->GPIO_Trig_Port = GPIO_Trig_Port;
Ultrasonic->GPIO_Trig_Pin = GPIO_Trig_Pin;
Ultrasonic->GPIO_Echo_Port = GPIO_Echo_Port;
Ultrasonic->GPIO_Echo_Pin = GPIO_Echo_Pin;
Ultrasonic->echoFlag = 0;
Ultrasonic->TIM_Counter = 0;
}
int Ultrasonic_getDistance(Ultrasonic_t *Ultrasonic)
{
int timeout = 0;
Ultrasonic_startTrig(Ultrasonic);
while (!Ultrasonic_isCmpltRecvEcho(Ultrasonic)) // Falling edge까지 대기
{
timeout++;
if (timeout > 20) // 타임아웃 처리
return 0;
HAL_Delay(1);
}
Ultrasonic_clearEchoFlag(Ultrasonic);
return Ultrasonic->TIM_Counter * 0.034 / 2; //cm distance
}
void Ultrasonic_ISR_Process(Ultrasonic_t *Ultrasonic, uint16_t GPIO_Pin)
{
if (GPIO_Pin == Ultrasonic->GPIO_Echo_Pin)
{
// Echo pin High 유지시간 측정
if (Ultrasonic_getEchopinState(Ultrasonic)) // Rising edge
{
//TIM1->CNT
Ultrasonic_clearTimer(Ultrasonic); // TIM1 동작 전 CNT 초기화
Ultrasonic_startTimer(Ultrasonic); // Rising edge이면 TIM1 동작 시작
Ultrasonic_clearEchoFlag(Ultrasonic);
}
else // Falling edge
{
Ultrasonic_stopTimer(Ultrasonic); // Falling edge이면 TIM1 동작 종료
Ultrasonic->TIM_Counter = Ultrasonic_getTimerCounter(Ultrasonic); // TIM1 CNT 값 읽기
Ultrasonic_setEchoFlag(Ultrasonic);
}
}
}
void Ultrasonic_clearTimer(Ultrasonic_t *Ultrasonic)
{
__HAL_TIM_SET_COUNTER(Ultrasonic->TIM_handle, 0);
}
void Ultrasonic_startTimer(Ultrasonic_t *Ultrasonic)
{
HAL_TIM_Base_Start(Ultrasonic->TIM_handle);
}
void Ultrasonic_stopTimer(Ultrasonic_t *Ultrasonic)
{
HAL_TIM_Base_Stop(Ultrasonic->TIM_handle);
}
uint16_t Ultrasonic_getTimerCounter(Ultrasonic_t *Ultrasonic)
{
return __HAL_TIM_GET_COUNTER(Ultrasonic->TIM_handle);
}
int Ultrasonic_getEchopinState(Ultrasonic_t *Ultrasonic)
{
return HAL_GPIO_ReadPin(Ultrasonic->GPIO_Echo_Port, Ultrasonic->GPIO_Echo_Pin);
}
void Ultrasonic_startTrig(Ultrasonic_t *Ultrasonic)
{
HAL_GPIO_WritePin(Ultrasonic->GPIO_Trig_Port, Ultrasonic->GPIO_Trig_Pin, SET);
//HAL_Delay(1);
DelayUS(15);
HAL_GPIO_WritePin(Ultrasonic->GPIO_Trig_Port, Ultrasonic->GPIO_Trig_Pin, RESET);
}
int Ultrasonic_isCmpltRecvEcho(Ultrasonic_t *Ultrasonic)
{
return Ultrasonic->echoFlag;
}
void Ultrasonic_clearEchoFlag(Ultrasonic_t *Ultrasonic)
{
Ultrasonic->echoFlag = 0;
}
void Ultrasonic_setEchoFlag(Ultrasonic_t *Ultrasonic)
{
Ultrasonic->echoFlag = 1;
}

/*
* AP_Main.c
*
* Created on: Apr 23, 2024
* Author: k1min
*/
#include "AP_Main.h"
#include "stdio.h"
extern TIM_HandleTypeDef htim1, htim2, htim3;
Button_t Button_1, Button_2, Button_3;
LED_t LED_1, LED_2, LED_3;
Ultrasonic_t Ultrasonic_1, Ultrasonic_2, Ultrasonic_3;
uint8_t mode_State;
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
Ultrasonic_ISR_Process(&Ultrasonic_1, GPIO_Pin);
Ultrasonic_ISR_Process(&Ultrasonic_2, GPIO_Pin);
Ultrasonic_ISR_Process(&Ultrasonic_3, GPIO_Pin);
}
void sys_init()
{
button_init(&Button_1, GPIOC, GPIO_PIN_10);
button_init(&Button_2, GPIOC, GPIO_PIN_11);
button_init(&Button_3, GPIOC, GPIO_PIN_12);
LED_init(&LED_1, GPIOC, GPIO_PIN_8);
LED_init(&LED_2, GPIOC, GPIO_PIN_6);
LED_init(&LED_3, GPIOC, GPIO_PIN_5);
Ultraosnic_init(&Ultrasonic_1, &htim1, GPIOC, GPIO_PIN_0, GPIOC, GPIO_PIN_1);
Ultraosnic_init(&Ultrasonic_2, &htim2, GPIOB, GPIO_PIN_0, GPIOA, GPIO_PIN_4);
Ultraosnic_init(&Ultrasonic_3, &htim3, GPIOC, GPIO_PIN_3, GPIOC, GPIO_PIN_2);
LCD_init();
DelayInit();
mode_State = defaultLED;
}
int APMain()
{
sys_init();
LCD_writeStringXY(0, 0, "Hello STM32!");
LCD_writeStringXY(1, 0, "KCCISTC Harman");
char buff[50];
int distance;
while (1)
{
if (button_getState(&Button_1) == ACT_RELEASED)
{
distance = Ultrasonic_getDistance(&Ultrasonic_1);
if(distance > 150) distance = 150;
sprintf(buff, "dis:%dcm ", distance);
LCD_writeStringXY(0, 0, buff);
}
if (button_getState(&Button_2) == ACT_RELEASED)
{
distance = Ultrasonic_getDistance(&Ultrasonic_2);
if(distance > 150) distance = 150;
sprintf(buff, "dis:%dcm ", distance);
LCD_writeStringXY(1, 0, buff);
}
if (button_getState(&Button_3) == ACT_RELEASED)
{
distance = Ultrasonic_getDistance(&Ultrasonic_3);
if(distance > 150) distance = 150;
sprintf(buff, "%dcm ", distance);
LCD_writeStringXY(0, 0, buff);
}
}
return 0;
}
void modeStateCheck()
{
if (button_getState(&Button_1) == ACT_PUSHED)
{
mode_State = LED1_ON;
LED_OFF(&LED_1);
LED_OFF(&LED_2);
LED_OFF(&LED_3);
}
if (button_getState(&Button_2) == ACT_PUSHED)
{
mode_State = LED2_3_ON;
LED_OFF(&LED_1);
LED_OFF(&LED_2);
LED_OFF(&LED_3);
}
if (button_getState(&Button_3) == ACT_PUSHED)
{
mode_State = LED1_3_ON;
LED_OFF(&LED_1);
LED_OFF(&LED_2);
LED_OFF(&LED_3);
}
}
void modeStateRun()
{
static uint32_t prevTime = 0;
uint32_t curTime = HAL_GetTick();
switch (mode_State)
{
case LED1_ON:
if(curTime - prevTime < 200)
return;
prevTime = curTime;
// if (timeTick != 0)
// return;
LED_toggle(&LED_1);
LED_OFF(&LED_2);
LED_OFF(&LED_3);
// timeTick = 200;
break;
case LED2_3_ON:
if(curTime - prevTime < 100)
return;
prevTime = curTime;
// if (timeTick != 0)
// return;
LED_toggle(&LED_2);
LED_toggle(&LED_3);
LED_OFF(&LED_1);
// timeTick = 100;
break;
case LED1_3_ON:
if(curTime - prevTime < 1000)
return;
prevTime = curTime;
// if (timeTick != 0)
// return;
LED_toggle(&LED_1);
LED_toggle(&LED_3);
LED_OFF(&LED_2);
// timeTick = 1000;
break;
case defaultLED:
if(curTime - prevTime < 500)
return;
prevTime = curTime;
// if (timeTick != 0)
// return;
LED_toggle(&LED_1);
LED_toggle(&LED_2);
LED_toggle(&LED_3);
// timeTick = 500;
break;
}
}
[전체 코드]
GitHub - k1minseok/STM32_Ultrasonic_Driver_0424
Contribute to k1minseok/STM32_Ultrasonic_Driver_0424 development by creating an account on GitHub.
github.com
Made By Minseok KIM
'ARM > 2_Study' 카테고리의 다른 글
[ARM] STM32_FreeRTOS, Shared Memory (0) | 2024.04.30 |
---|---|
[ARM] STM32_Serial Communication(UART), Queue (0) | 2024.04.29 |
[ARM] STM32_PWM, Driver(Motor) (0) | 2024.04.29 |
[ARM] STM32_메모리 저장&실행 과정, Driver(Button, LED) (0) | 2024.04.26 |
[ARM] STM32_Low level Programming (0) | 2024.04.24 |
Let's Be Happy!
도움이 되었으면 좋겠어요 :)