STM32 프로젝트
ST Nucleo L031K6을 이용한 ADC 읽기 및 출력 제어 프로젝트
모빌리티키즈
2025. 5. 31. 11:21
728x90
반응형
이 프로젝트에서는 ST Nucleo L031K6을 활용하여 ADC(아날로그-디지털 변환기)로 전압 값을 읽고, 특정 조건에 따라 GPIO 출력 핀을 제어하는 시스템을 구현합니다. 아날로그 입력은 A1 핀을 통해 읽으며, 결과에 따라 PB0~PB7 핀의 상태가 변경됩니다.
🛠️ 사용 부품 및 기능
- ST Nucleo L031K6: 저전력 마이크로컨트롤러
- ADC(아날로그-디지털 변환기): 아날로그 신호를 디지털 값으로 변환
- GPIO 출력 핀 (PB0 - PB7): 디지털 신호 제어
- RCC 시스템 클럭: GPIO 및 ADC 활성화
- 전압 임계값 설정: ADC 읽기 값에 따라 출력 변경
⚡ 하드웨어 설정
코드에서는 두 개의 전압 임계값을 정의합니다.
- V1 = 1861 (1.5V)
- V2 = 3722 (3V)
ADC는 채널 1(A1 핀)을 사용하며, 읽어온 값에 따라 GPIOB 출력이 변경됩니다.
💻 코드 설명
🏗️ 핀 및 ADC 초기화
void inicio(void) {
RCC->IOPENR |= 0b00000000000000000000000000000011; // GPIOA 및 GPIOB 활성화
GPIOB->MODER &= 0b11111111111111110101010101110101; // PB0~PB7을 출력 모드로 설정
RCC->APB2ENR |= 0b00000000000000000000001000000000; // ADC 클럭 활성화
ADC1->CHSELR |= 0b00000000000000000000000000000010; // ADC 채널 1 활성화
ADC1->CR |= 0b00000000000000000000000000000001; // ADC 활성화
}
- GPIO 및 ADC 클럭을 활성화
- PB0~PB7을 출력으로 설정
- ADC 채널 1 활성화 및 준비 완료
🔄 메인 루프 및 출력 제어
int main(void) {
Serial.begin(9600);
inicio();
while (1) {
pot = lectura(); // ADC 값 읽기
Serial.println(pot); // 읽은 값 출력
if (pot < V1) {
GPIOB->BSRR |= 0b00000000111110110000000000000000; // 모든 출력 OFF
}
if (pot >= V1 && pot < V2) {
GPIOB->BSRR |= 0b00000000111110110000000000000000;
GPIOB->ODR |= 0b00000000000000000000000000001011; // 일부 출력 ON
}
if (pot >= V2) {
GPIOB->ODR |= 0b00000000000000000000000011111011; // 모든 출력 ON
}
}
}
ADC 읽기 값에 따라 GPIO 출력 핀이 변경됩니다.
- pot < V1: 모든 출력 OFF
- V1 ≤ pot < V2: 일부 출력 ON
- pot ≥ V2: 모든 출력 ON
🏗️ ADC 데이터 읽기
int lectura() {
ADC1->CR |= 0b00000000000000000000000000000100; // ADC 변환 시작
while ((ADC1->ISR & 0b1 << 1) == 0); // 변환 완료될 때까지 대기
return ADC1->DR; // 변환된 데이터 반환
}
- ADC 변환을 시작
- 변환 완료 시까지 대기
- 변환된 디지털 값 반환
🏗️ 전체 소스
int V1=1861; //primer umbral de voltaje 1.5V corresponde a 4095/3.3*1.5 uint16_t
int V2=3722; //segundo umbral de voltaje 3V corresponde a 4095/3,3*3
int pot;
//----- Función para habilitar puertos y configurar pines
void inicio(void) {
// Habilita el reloj del puerto GPIOA y B
RCC->IOPENR |= 0b00000000000000000000000000000011;
// Configura los pines PB0, 1, 3, 4, 5, 6 y 7 como salida.
GPIOB->MODER &= 0b11111111111111110101010101110101;
//(A1 viene configurado por defecto como entrada analógica (11))
//GPIOB->ODR |= 0b00000000000000000000000011111011; comentado, solo ejecuto para ver si las salidas funcionan bien (sí lo hacen)
// Habilita el reloj para el ADC.
RCC->APB2ENR |= 0b00000000000000000000001000000000;
// Habilita el canal 1, asociado al pin A1, como entrada analógica
ADC1->CHSELR |= 0b00000000000000000000000000000010;
//Habilita el conversor A/D. Esto se consigue poniendo a '1' el bit ADEN (bit 0 del registro).
ADC1->CR |= 0b00000000000000000000000000000001;
}
int main(void) {
Serial.begin(9600);
// Inicialización de pines
inicio();
// Bucle infinito
while (1) {
pot=lectura();
Serial.println(pot);
if (pot<V1){GPIOB->BSRR |= 0b00000000111110110000000000000000;}
if (pot>=V1 && pot<V2){GPIOB->BSRR |= 0b00000000111110110000000000000000;
GPIOB->ODR |= 0b00000000000000000000000000001011;}
if (pot>=V2){GPIOB->ODR |= 0b00000000000000000000000011111011;}
}
}
int lectura (){
//Inicia la conversión A/D. Para ello es necesario poner a '1' el bit ADSTART (bit 2 del registro).
ADC1->CR |= 0b00000000000000000000000000000100;
//espera mientras acaba la conversión A/D
while ((ADC1->ISR & 0b1<<1) == 0);
return ADC1->DR;
}
🏁 결론
이 프로젝트에서는 ST Nucleo L031K6의 ADC 기능을 활용하여 전압 값에 따라 디지털 출력을 제어하는 방법을 구현했습니다. 추가적으로 PWM을 이용한 출력 제어 또는 OLED 디스플레이 연동과 같은 확장 기능을 고려할 수도 있습니다!
다른 센서를 추가하거나 Wi-Fi 연결을 활용한 IoT 기능을 적용해보는 것도 좋은 아이디어겠네요. 😊
728x90
반응형