[FPGA] 세탁기 프로젝트
2021. 11. 30. 11:21ㆍ코딩/FPGA
AVR-FPGA 를 이용하여 세탁기 모형 제작
FPGA 블록도


상태천이도

MAIN.c
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "button.h"
#include "buzzer.h"
#include "lcd_4bit.h"
#include "mode.h"
int main(void)
{
pwmInit();
char buff[30];
LCD_Init();
int count = 0;
modeState = mainmenu;
while (1)
{
select_mode();
}
}
LCD_4bit.c
#include "lcd_4bit.h"
uint8_t lcdData = 0;
void slaveSelect(uint8_t state)
{
if (state == LOW)
{
LCD_SS_PORT &= !(1<<LCD_SS);
}
else
{
LCD_SS_PORT |= (1<<LCD_SS);
}
}
void shiftClock()
{
LCD_SHIFT_CLK_PORT |= (1<<LCD_SHIFT_CLK);
LCD_SHIFT_CLK_PORT &= ~(1<<LCD_SHIFT_CLK);
}
void LCD_Data(uint8_t data)
{
//LCD_DATA_PORT = data // 8bit data 전소
//8bit serial 전송,msb부터 전송
//0b11001010
//i_ss핀을 low로 만든다.
slaveSelect(LOW);
for (int i=0; i<8; i++)
{
if (data & (0x80>>i)) LCD_MOSI_PORT |= (1<<LCD_MOSI);
else LCD_MOSI_PORT &= ~(1<<LCD_MOSI);
shiftClock();
}
//i_ss핀을 high로 만든다
slaveSelect(HIGH);
}
void LCD_Data4bit(uint8_t data)
{
lcdData = (lcdData & 0x0f) | (data & 0xf0); // 상위 4bit 출력
LCD_EnablePin();
lcdData = (lcdData & 0x0f) | ((data & 0x0f) << 4); // 하위 4bit 출력
LCD_EnablePin();
}
void LCD_Data4bitInit(uint8_t data)
{
lcdData = (lcdData & 0x0f) | (data & 0xf0); // 상위 4bit 출력
LCD_EnablePin();
}
void LCD_WriteMode()
{
lcdData &= ~(1<<LCD_RW);
}
void LCD_EnablePin()
{
lcdData &= ~(1<<LCD_E);
LCD_Data(lcdData);
lcdData |= (1<<LCD_E);
LCD_Data(lcdData);
lcdData &= ~(1<<LCD_E);
LCD_Data(lcdData);
_delay_us(1600);
}
void LCD_WriteCommand(uint8_t commadData)
{
lcdData &= ~(1<<LCD_RS);
LCD_WriteMode();
LCD_Data4bit(commadData);
}
void LCD_WriteCommandInit(uint8_t commadData)
{
lcdData &= ~(1<<LCD_RS);
LCD_WriteMode();
LCD_Data4bitInit(commadData);
}
void LCD_WriteData(uint8_t charData)
{
lcdData |= (1<<LCD_RS);
LCD_WriteMode();
LCD_Data4bit(charData);
}
void LCD_GotoXY(uint8_t row, uint8_t col)
{
col %= 16;
row %= 2;
uint8_t address = (0x40 * row) + col;
uint8_t command = 0x80 + address;
LCD_WriteCommand(command);
}
void LCD_WriteString(char *string)
{
for (uint8_t i=0; string[i]; i++)
{
LCD_WriteData(string[i]);
}
}
void LCD_WriteStringXY(uint8_t row, uint8_t col, char *string)
{
LCD_GotoXY(row, col);
LCD_WriteString(string);
}
void LCD_Init()
{
LCD_DATA_DDR = 0xff;
LCD_RS_DDR |= (1<<LCD_RS);
LCD_RW_DDR |= (1<<LCD_RW);
LCD_E_DDR |= (1<<LCD_E);
LCD_SHIFT_CLK_DDR |= (1<<LCD_SHIFT_CLK);
LCD_MOSI_DDR |= (1<<LCD_MOSI);
LCD_SS_DDR |= (1<<LCD_SS);
_delay_ms(20);
LCD_WriteCommand(0x03);
_delay_ms(5);
LCD_WriteCommand(0x03);
_delay_ms(1);
LCD_WriteCommand(0x03);
LCD_WriteCommand(0x02);
LCD_WriteCommand(COMMAND_4_BIT_MODE);
LCD_WriteCommand(COMMAND_DISPLAY_OFF);
LCD_WriteCommand(COMMAND_DISPLAY_CLEAR);
LCD_WriteCommand(COMMAND_ENTRY_MODE);
LCD_WriteCommand(COMMAND_DISPLAY_ON);
}
MODE.c
#include "mode.h"
#include "button.h"
#include "lcd_4bit.h"
void select_mode()
{
switch (modeState)
{
case mainmenu:
sprintf(buff, "--select mode--");
LCD_WriteStringXY(0, 0, buff);
sprintf(buff, "1.wash 2.dry");
LCD_WriteStringXY(1, 0, buff);
_delay_ms(100);
if(getButton1State())
{
modeState = washmode;
}
if(getButton2State())
{
modeState = drymode;
}
break;
case washmode:
sprintf(buff, " --wash mode-- ");
LCD_WriteStringXY(0, 0, buff);
sprintf(buff, "count: %d ", timecount);
LCD_WriteStringXY(1, 0, buff);
if(getButton1State())
{
timecount = timecount +5;
}
if(getButton2State())
{
modeState = start;
}
_delay_ms(100);
break;
case drymode:
sprintf(buff, " --dry mode-- ");
LCD_WriteStringXY(0, 0, buff);
break;
case start:
if (timecount >= 1)
{
sprintf(buff, "count: %3d", timecount--);
LCD_WriteStringXY(1, 0, buff);
_delay_ms(100);
}
else if (timecount == 0)
{
sprintf(buff, "count: %3d", timecount);
LCD_WriteStringXY(1, 0, buff);
_delay_ms(100);
modeState = mainmenu;
}
break;
}
}
BUTTON.c
#include "button.h"
#include "buzzer.h"
void buttonInit()
{
BUTTON1_DDR &= ~(1<<BUTTON1);
BUTTON2_DDR &= ~(1<<BUTTON2);
BUTTON3_DDR &= ~(1<<BUTTON3);
}
uint8_t getButton1State()
{
static uint8_t prevButton1State = RELEASED; //기존 값 유지 변수유지
uint8_t curButtonState = BUTTON1_PIN &(1<<BUTTON1);
if((curButtonState == PUSHED)&&(prevButton1State == RELEASED)) //처음 누른 상태
{
_delay_ms(20);
prevButton1State = PUSHED;
return FALSE;
}
else if((prevButton1State == PUSHED)&&(curButtonState != PUSHED)) //버튼을 땠을때
{
_delay_ms(20);
prevButton1State = RELEASED;
return TRUE;
}
return FALSE;
}
uint8_t getButton2State()
{
static uint8_t prevButton2State = RELEASED; //기존 값 유지 변수유지
uint8_t curButtonState = BUTTON2_PIN &(1<<BUTTON2);
if((curButtonState == PUSHED)&&(prevButton2State == RELEASED)) //처음 누른 상태
{
_delay_ms(30); //debouncing 때문에 딜레이를 준다. 노이즈때문에, 두 번 바뀌는 경우가 있다.
prevButton2State = PUSHED;
return FALSE;
}
else if((prevButton2State == PUSHED)&&(curButtonState != PUSHED)) //버튼을 땠을때
{
_delay_ms(30);
prevButton2State = RELEASED;
return TRUE;
}
return FALSE;
}
uint8_t getButton3State()
{
static uint8_t prevButton3State = RELEASED; //기존 값 유지 변수유지
uint8_t curButtonState = BUTTON3_PIN &(1<<BUTTON3);
if((curButtonState == PUSHED)&&(prevButton3State == RELEASED)) //처음 누른 상태
{
_delay_ms(30); //debouncing 때문에 딜레이를 준다. 노이즈때문에, 두 번 바뀌는 경우가 있다.
prevButton3State = PUSHED;
return FALSE;
}
else if((prevButton3State == PUSHED)&&(curButtonState != PUSHED)) //버튼을 땠을때
{
_delay_ms(30);
prevButton3State = RELEASED;
return TRUE;
}
return FALSE;
}
uint8_t getButton4State()
{
static uint8_t prevButton4State = RELEASED; //기존 값 유지 변수유지
uint8_t curButtonState = BUTTON4_PIN &(1<<BUTTON4);
if((curButtonState == PUSHED)&&(prevButton4State == RELEASED)) //처음 누른 상태
{
_delay_ms(30); //debouncing 때문에 딜레이를 준다. 노이즈때문에, 두 번 바뀌는 경우가 있다.
prevButton4State = PUSHED;
return FALSE;
}
else if((prevButton4State == PUSHED)&&(curButtonState != PUSHED)) //버튼을 땠을때
{
_delay_ms(30);
prevButton4State = RELEASED;
return TRUE;
}
return FALSE;
}
세탁기 프로젝트를 진행하면서 LCD Shift register, PWM, interrupt 에 관하여 한번더 공부를 할 수가 있었습니다.
저번 유사한 프로젝트에서 부족했던 부분을 이번 프로젝트 에서는 보강을 할수 있었기 때문에 그부분은 만족스러웠습니다.
다만 너무 기본적인 기능들만 제공 하였기 때문에 다음에 기회가 있다면 한층 더 보강하여 제작을 하고 싶습니다.
세탁, 탈수에 각기 다른 PWM을 적용시켰는데 현재 상태가 LCD에 표기가 되니 각기 다른 PWM을 적용 시키는게 아니라 각 기능에 강,중,약 기능을 추가하는것이 좋았을거라는 생각이 들어서 아쉬웠습니다.
'코딩 > FPGA' 카테고리의 다른 글
[FPGA]FPGA 보드에 CPU 코어 만들기 MicroBlaze 사용 (0) | 2021.11.17 |
---|---|
[FPGA] FPGA+ AVR Buzzer + Motor (0) | 2021.11.12 |
[FPGA] FPGA + AVR StopWatch (0) | 2021.11.12 |
FPGA IP PACKAGE 하는 방법 (0) | 2021.11.12 |
[FPGA] Stopwatch + Clock + LED bar (0) | 2021.11.10 |