기존 simple traffic system 과의 차이점
- button & led 드라이버로 분리
- ap 라는 동작 모듈 분리
-> main.c에서 동작 함수만을 불러와서 사용하도록 수정
1. main.c
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include "driver/led/led.h"
#include "driver/button/button.h"
#include "driver/ap/trafficSignal.h"
int main(void)
{
trafficSignal_init();
while (1)
{
trafficSignal_RUN();
}
}
- trafficSignal_init() : port 할당 및 초기화
- trafficSignal_RUN() : 동작 수행
2. ap
- trafficSignal.h
/*
* trafficSignal.h
*
* Created: 2024-09-20 오후 1:36:29
* Author: kccistc
*/
#ifndef TRAFFICSIGNAL_H_
#define TRAFFICSIGNAL_H_
#include "../button/button.h"
#include "../led/led.h"
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#define TRAFFIC_BUTTON_AUTO 0
#define TRAFFIC_BUTTON_MANUAL 1
#define TRAFFIC_BUTTON_SWITCH 2
#define TRAFFIC_SIGNAL_VGREEN 0
#define TRAFFIC_SIGNAL_VYELLOW 1
#define TRAFFIC_SIGNAL_VRED 2
#define TRAFFIC_SIGNAL_HGREEN 3
#define TRAFFIC_SIGNAL_HYELLOW 4
#define TRAFFIC_SIGNAL_HRED 5
enum {AUTO, MANUAL};
enum {RED_GREEN, RED_YELLOW, GREEN_RED, YELLOW_RED};
void TrafficSignal_AUTO();
void TrafficSignal_MANUAL();
void trafficSignal_REDGREEN();
void trafficSignal_REDYELLOW();
void trafficSignal_GREENRED();
void trafficSignal_YELLOWRED();
void trafficSignal_init();
void trafficSignal_RUN();
#endif /* TRAFFICSIGNAL_H_ */
- trafficSignal.c
/*
* trafficSignal.c
*
* Created: 2024-09-20 오후 1:36:17
* Author: kccistc
*/
#include "trafficSignal.h"
uint8_t trafficState;
uint8_t trafficLedState;
uint8_t trafficLedData;
uint32_t timeTick;
button_t btnAuto, btnManual, btnSwitch;
led_t ledTraffic;
void trafficSignal_init(){
trafficState = AUTO;
trafficLedState = RED_GREEN;
timeTick = 0;
// LED GPIO 6 pin
led_init(&ledTraffic, &DDRE, &PORTE, TRAFFIC_SIGNAL_VRED);
led_init(&ledTraffic, &DDRE, &PORTE, TRAFFIC_SIGNAL_VYELLOW);
led_init(&ledTraffic, &DDRE, &PORTE, TRAFFIC_SIGNAL_VGREEN);
led_init(&ledTraffic, &DDRE, &PORTE, TRAFFIC_SIGNAL_HRED);
led_init(&ledTraffic, &DDRE, &PORTE, TRAFFIC_SIGNAL_HYELLOW);
led_init(&ledTraffic, &DDRE, &PORTE, TRAFFIC_SIGNAL_HGREEN);
// BUTTON GPIO 3 pin
PORTA = 0xff;
Button_init(&btnAuto, &DDRA, &PINA, 0);
Button_init(&btnManual, &DDRA, &PINA, 1);
Button_init(&btnSwitch, &DDRA, &PINA, 2);
}
void trafficSignal_RUN(){
//AUTO-MANUAL mode Event Check
if (Button_GetState(&btnAuto) == ACT_RELEASED)
{
trafficState = AUTO;
}
else if(Button_GetState(&btnManual) == ACT_RELEASED)
{
trafficState = MANUAL;
}
// auto-manual mode RUN
switch(trafficState)
{
case AUTO :
TrafficSignal_AUTO();
break;
case MANUAL :
TrafficSignal_MANUAL();
break;
}
_delay_ms(1);
timeTick++;
}
void TrafficSignal_AUTO()
{
//static uint8_t trafficAutoState = RED_GREEN;
static uint32_t prevTime = 0;
switch(trafficLedState)
{
case RED_GREEN :
trafficSignal_REDGREEN();
//_delay_ms(3000);
if(timeTick - prevTime >= 3000)
{
prevTime = timeTick;
trafficLedState = RED_YELLOW;
}
break;
case RED_YELLOW :
trafficSignal_REDYELLOW();
//_delay_ms(1000);
if(timeTick - prevTime >= 1000)
{
prevTime = timeTick;
trafficLedState = GREEN_RED;
}
break;
case GREEN_RED :
trafficSignal_GREENRED();
//_delay_ms(3000);
if(timeTick - prevTime >= 3000)
{
prevTime = timeTick;
trafficLedState = YELLOW_RED;
}
break;
case YELLOW_RED :
trafficSignal_YELLOWRED();
//_delay_ms(1000);
if(timeTick - prevTime >= 1000)
{
prevTime = timeTick;
trafficLedState = RED_GREEN;
}
break;
}
}
void TrafficSignal_MANUAL()
{
//static uint8_t trafficAutoState = RED_GREEN;
switch(trafficLedState)
{
case RED_GREEN :
trafficSignal_REDGREEN();
if ((Button_GetState(&btnSwitch)) == ACT_RELEASED)
{
trafficLedState = RED_YELLOW;
}
break;
case RED_YELLOW :
trafficSignal_REDYELLOW();
if ((Button_GetState(&btnSwitch)) == ACT_RELEASED)
{
trafficLedState = GREEN_RED;
}
break;
case GREEN_RED :
trafficSignal_GREENRED();
if ((Button_GetState(&btnSwitch)) == ACT_RELEASED)
{
trafficLedState = YELLOW_RED;
}
break;
case YELLOW_RED :
trafficSignal_YELLOWRED();
if ((Button_GetState(&btnSwitch)) == ACT_RELEASED)
{
trafficLedState = RED_GREEN;
}
break;
}
}
void trafficSignal_REDGREEN()
{
trafficLedData = (1<<TRAFFIC_SIGNAL_VRED)|(1<<TRAFFIC_SIGNAL_HGREEN);
led_writeData(trafficLedData);
}
void trafficSignal_REDYELLOW()
{
trafficLedData = (1<<TRAFFIC_SIGNAL_VRED) | (1<<TRAFFIC_SIGNAL_HYELLOW);
led_writeData(trafficLedData);
}
void trafficSignal_GREENRED()
{
trafficLedData = (1<<TRAFFIC_SIGNAL_VGREEN) | (1<<TRAFFIC_SIGNAL_HRED);
led_writeData(trafficLedData);
}
void trafficSignal_YELLOWRED()
{
trafficLedData = (1<<TRAFFIC_SIGNAL_VYELLOW) | (1<<TRAFFIC_SIGNAL_HRED);
led_writeData(trafficLedData);
}
3. driver - button
- button.h
#ifndef BUTTON_H_
#define BUTTON_H_
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
enum {PUSHED, RELEASED};
enum {ACT_PUSHED, ACT_RELEASED, ACT_NONE};
typedef struct _button{
volatile uint8_t *DDR; // port
volatile uint8_t *PIN; // pin
uint8_t pinNum; // pin number
uint8_t prevState; // prevState variable
}button_t;
void Button_init(button_t *btn, volatile uint8_t *ddr, volatile uint8_t *pin, uint8_t pinNum);
uint8_t Button_GetState(button_t *btn);
#endif /* BUTTON_H_ */
button에 대한 ddr, pin, 사용할 pinNumber, prevState에 대한 정보를 포함하는 구조체 생성 후 사용
- button.c
#include "button.h"
void Button_init(button_t *btn, volatile uint8_t *ddr, volatile uint8_t *pin, uint8_t pinNum){
btn->DDR = ddr;
btn->PIN = pin;
btn->pinNum = pinNum;
btn->prevState = RELEASED;
*btn->DDR &= ~(1<<btn->pinNum); //
}
uint8_t Button_GetState(button_t *btn){
uint8_t curState = (*btn->PIN) & (1<<btn->pinNum); // 현재 버튼이 눌렸는가를 보여주는 상태
if ((curState == PUSHED) && (btn->prevState == RELEASED)){
_delay_ms(10); // chattering 방지 위한 D bounce code
btn->prevState = PUSHED;
return ACT_PUSHED;
}
// 눌렀다 뗄 때
else if ((curState != PUSHED) && (btn->prevState == PUSHED)){
_delay_ms(10);
btn->prevState = RELEASED;
return ACT_RELEASED;
}
return ACT_NONE;
}
4. driver - led
- led.h
/*
* led.h
*
* Created: 2024-09-20 오전 11:26:30
* Author: kccistc
*/
#ifndef LED_H_
#define LED_H_
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#define LED_DDR DDRE
#define LED_PORT PORTE
#define LED_PIN PINE
typedef struct _led{
volatile uint8_t *DDR;
volatile uint8_t *PORT;
uint8_t pinNum;
}led_t;
void led_init(led_t *led, volatile uint8_t *ddr, volatile uint8_t *port, uint8_t pinNum);
void led_writeData(uint8_t data);
void led_allOFF();
void led_allON();
#endif /* LED_H_ */
- led.c
#include "led.h"
// led initializing
void led_init(led_t *led, volatile uint8_t *ddr, volatile uint8_t *port, uint8_t pinNum){
led->DDR = ddr;
led->PORT = port;
led->pinNum = pinNum;
*led->DDR |= (1<<led->pinNum);
}
// led lighting
void led_writeData(uint8_t data){
LED_PORT = data;
}
void led_allOFF(){
LED_PORT = 0x00;
}
void led_allON(){
LED_PORT = 0xff;
}
'하만 세미콘 아카데미 8기 > 임베디드 시스템을 위한 sw 구조설계' 카테고리의 다른 글
atmega128a - led machine (+ driver) (0) | 2024.09.22 |
---|---|
atmega128a - simple traffic system (0) | 2024.09.22 |
240911 avr atmega led & switch 실습 - 1 (0) | 2024.09.13 |