1. 회로

- PORTE.0/1 : RX/TX
앞면 : 다운로딩 및 컴퓨터 ComPortMaster용
뒷면 : 핸드폰용
2. 프로그램 설계
- UART는 블루투스와 컴퓨터 둘다 가능하도록 코딩하였습니다.
- Uart는 패킷을 통해 완성된 문장을 보내게 되는데 각 패킷은 <>으로 시작과 끝을 만듭니다.
- 패킷의 종류로는 전체 센서 제어용 패킷과 타이머 온오프 패킷 응급상황 패킷, 문 열림 패킷이 있습니다.
- UART로 각종 센서를 전체적으로 제어 할 수가 있습니다.
[UART 필요 기능]
패킷 종류 | 센서 제어용 패킷 : <LAON> <LAOFF> 타이머 제어용 패킷 : <T시간> <TOFF> 응급상황 패킷 : <EOFF> (= 문 닫힘) 문 열림 패킷 <OPEN> |
다른 센서와의 데이터 교환 | 다른 센서와 데이터 처리를 하기 위한 여러 전역 변수를 설정했습니다. timerCnt, isTimerOn, isRunning, isTimerDone |
타이머 시간 처리 | UART로 들어온 시간은 문자로 되어있습니다. 따라서 해당 문자를 숫자로 변환하여 변환한 숫자를 userTimeInput에. 저장한 후 Timer를 On한 후 타이머 내부에서 데이터를 처리합니다. |
예외 처리 |
타이머 동작시 다시 동작을 막거나 타이머를 도중에 끄기, 시간값에 문자가 들어가있거나, 타이머에 9999이상의 시간 값이 들어가 있을 때 를 방지하기 위한 코드를 추가합니다. |
3. 동작 방식
- uart 통신은 직렬 통신 방식중 한 프로토콜입니다.
- 인터럽트 방식과 폴링 방식 둘다 사용 가능하지만 이 프로젝트에서는 인터럽트 방식을 사용했습니다. 그 이유로 여러 어떤 동작 중에도 사용자의 입력이 즉시 적용해야 할 것이라 생각했습니다.
- RX 인터럽트로 UDR1을 통해 사용자가 입력한 데이터를 가져오거나 다시 에코백을 할 수 있습니다
4. 프로그램
[uart.c]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
|
#include "header.h"
#include "uart.h"
#include "lcd.h"
#include "timer.h"
#include <string.h>
/*
* USART1 = 보드
* USART0 = 블루투스
*/
/*
* 입력 받는 단어 1개
*/
char chComInput;
char chBTInput;
/*
* 패킷완성을 위한 문자열
*/
char strComInput[20] = {0,};
char strBTInput[20] = {0,};
/*
* 입력받은 갯수
*/
int inputComCount = 0;
int inputBTCount = 0;
void Init_USART1(void){
UCSR1A = 0x00; // 1배속 전송모드, 생략 가능
UCSR1B = (1<<RXEN1) | (1 <<TXEN1) | (1<<RXCIE1);
UCSR1C = (1<<UCSZ11) | (1<<UCSZ10); //생략 가능 레지스터 초기값
UCSR1C &= ~(1<<UMSEL1); // 비동기 모드의 선택, 생략 가능
UBRR1H = 0;
UBRR1L = 95; //9600bps
sei();
}
void Init_USART0(void){
UCSR0A=0x00; // 1배속 전송모드, 생략 가능
UCSR0B=0x98; // RX 인터럽트 수신 허가 | 수신허가 | 송신 허가
UCSR0C=0x06; //생략 가능 레지스터 초기값
UBRR0H=0;
UBRR0L=95;
}
/*
* 패킷처리
*/
void sensor_off(){ // 외출
PORTD = 0x00; // LED
PORTE = 0x00; // Timer
disp_some("Outing Now","", 1000);
}
void sensor_onoff(STATE state){ // LED ON OFF 패킷 확인
char *tempStr = NULL;
/* 두개의 UART중 하나라도 들어오면 해당 동작 수행 */
if(state == COM){
tempStr = strComInput;
}
else if(state == BT){
tempStr = strBTInput;
}
if (tempStr[4] == 'F'){ // OFF 패킷 = LOCK
sensor_off();
isAllSensorLock = true;
isTimerOn = false;
}
else if(tempStr[4] == 'N'){ // ON 패킷 = LOCK 해제
disp_some(Hello, madeBy, 3000);
isAllSensorLock = false;
isTimerOn = true;
}
}
void timer_set(STATE state){
char disp_time[5] = {0,};
char *tempStr = NULL;
int i=0;
if(strComInput[2] == '>'){return;} // <T>일때
if(isAllSensorLock){ // 모든 센서 LOCK일때는 불가 : 오류
lcdUserInputError = 2;
disp_some("ALL Sensor", "is Locked", 3000);
return;
}
/* 두개의 UART중 하나라도 들어오면 해당 동작 수행 */
if(state == COM){
tempStr = strComInput;
}
else if(state == BT){
tempStr = strBTInput;
}
/*
* 타이머 시작 신호
*/
timerCnt = 0;
userTimeInput = 0;
for( i=0; (i < 4) && (tempStr[2+i] != '>'); i++){
/*
* 패킷이 잘못 들어옴을 감지 : 오류
*/
if(tempStr[2+i] < '0' || tempStr[2+i] > '9'){
return;
}
disp_time[i] = tempStr[2+i];
userTimeInput *= 10;
userTimeInput += (tempStr[2+i] - '0');
}
/*
* 5자리 이상 감지 : 오류
*/
if(i == 4 && tempStr[6] != '>'){
lcdUserInputError = 1;
disp_some("timer Overflow","",3000);
return;
}
isTimerOn = true;
isRunning = true;
isTimerDone = false;
PORTD= 0x00;
disp_some("Timer Start : ",disp_time, 0);
}
/* 패킷 문자열 초기화 */
void str_reset(STATE state){
if(state == COM){
memset(strComInput,0,20);
inputComCount = 0;
}
else if(state == BT){
memset(strBTInput,0,20);
inputBTCount = 0;
}
}
void packet_processing(STATE state){
char *tempStr = NULL;
/* 두개의 UART중 하나라도 들어오면 해당 동작 수행 */
if (state == COM){
tempStr = strComInput;
}
else if (state == BT){
tempStr = strBTInput;
}
if(tempStr[1] != 'L' && tempStr[1] !='T' && tempStr[1] != 'E' && tempStr[1] != 'O') { // 패킷 입력 오류
lcdUserInputError = 3;
disp_some("Packet input", "is Locked", 3000);
str_reset(state);
}
else{
if(tempStr[1] == 'O'){ // OPEN
emergency_motor_degree();
}
if(tempStr[1] == 'L'){ // 센서 ON/OFF
sensor_onoff(state);
}
else if(tempStr[1] == 'T'){
if(tempStr[2] == 'O'){ // TOFF
PORTB=0x00;
isTimerOn = false; // 타이머 켜져있는 상태 막기
isRunning = false; // 타이머 켜지고 동작중
isTimerDone = false;
userTimeInput = 0;
lcdUserInputError=4;
disp_some("Timer is ","interrupted",3000);
PORTC = 0x00;
PORTE = 0x00;
str_reset(state);
}
else { // 숫자가 아닌 문자가 들어가면 문제 발생 해결, <T시간>
if(!isRunning){timer_set(state);}
}
}
else if(tempStr[1] == 'E' && tempStr[2] == 'O'){//<EOFF>
end_emergency();
isEmergency = false;
isAllSensorLock = false;
PORTD |= 0x80;
}
str_reset(state);
}
}
/*
* 전체 LED ON/OFF 패킷 : <LAOFF> / <LAON>
* 타이머 패킷 : <T830> / <T1010> / <TOFF>
* 응급상황 종료 <EOFF> 추가해야함
*/
/*
* COM
*/
ISR(USART1_RX_vect)
{
chComInput = UDR1;
UDR1 = chComInput; //echo back, 확인용
strComInput[inputComCount++] = chComInput;
if(inputComCount >= 10){ // 패킷 완성 안됨, 데이터 수 초과 -> 초기화
str_reset(COM);
}
if(strComInput[0] != '<'){ // packet 만족 못함 -> 초기화
str_reset(COM);
}
if(chComInput == '>'){
packet_processing(COM);
}
}
/*
* BT
*/
ISR(USART0_RX_vect)
{
chBTInput = UDR0;
UDR1 = chBTInput; //echo back
strBTInput[inputBTCount++] = chBTInput;
if(inputBTCount >= 10){ // 패킷 완성 안됨, 데이터 수 초과 -> 초기화
str_reset(BT);
}
if(strBTInput[0] != '<'){ // packet 만족 못함 -> 초기화
str_reset(BT);
}
if(chBTInput == '>'){
packet_processing(BT);
}
}
|
5. 결과
블루투스를 통한 UART <T10> 전달 후 동작 확인 | ![]() |
![]() |
|
노트북을 통한 UART 통신, <TOFF> 패킷 전달 후 동작 확인 |
![]() |
![]() |
'C (Atmega128)' 카테고리의 다른 글
5. 불꽃 감지 센서 및 모터 개발 (0) | 2022.02.27 |
---|---|
4. 조도 센서 (KY-018) (0) | 2022.02.27 |
3. Light Sensor (LM35) (0) | 2022.02.27 |
2. FND & Timer (0) | 2022.02.26 |
1. LCD (0) | 2022.02.26 |