키패드 버튼 4개를 누르면 FND에 왼쪽으로 shift되며 표시
- 키패드 ISR과 키패드 TASK의 동기화 : 키패드 task는 키패드 ISR로부터의 버튼 전달을 기다림. Keypad ISR에서 눌린 버튼을 전역변수(SendValue)를 통해 키패드 Task에 전달. 동기화를 위해 binary semaphore 사용.
- FND task는 Keypad Task로부터의 버튼 전달을 기다림. Keypad Task는 눌린 버튼을 전역 변수통해 FND task에 전달. FND task는 전달받은 버튼을 FND에 왼쪽으로 shift하며 표시
#include <FreeRTOS_AVR.h>
#define MS2TICKS(ms) (ms/portTICK_PERIOD_MS)
#define FND_SIZE 6
const int Keypad[4] = { 2, 3, 21, 20 };
const int FndSelectPin[6] = { 22, 23, 24, 25, 26, 27 };
const int FndPin[8] = { 30, 31, 32, 33, 34, 35, 36, 37 };
const int FndFont[10] = { 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x60, 0x7D, 0x07, 0x7F, 0x67 };
SemaphoreHandle_t Sem;
int SendValue = 0;
int Fnd[FND_SIZE] = {0,};
void ShiftInsert(int data){
int i;
for(i=1; i<FND_SIZE; i++){
Fnd[FND_SIZE - i] = Fnd[FND_SIZE - i - 1];
}
Fnd[0] = data;
}
void KeypadControl1(){
delay(50);
SendValue = 1;
xSemaphoreGive(sem);
}
void KeypadControl2(){
delay(50);
SendValue = 2;
xSemaphoreGive(sem);
}
void KeypadControl3(){
delay(50);
SendValue = 3;
xSemaphoreGive(sem);
}
void KeypadControl4(){
delay(50);
SendValue = 4;
xSemaphoreGive(sem);
}
void KeypadTask(){
int i, keypad;
while(1){
if(xSemaphoreTake(Sem, portMAX_DELAY)){
keypad = SendValue;
ShiftInsert(keypad):
}
}
}
void FndSelect(int pos){
int i;
for(i=0; i<6; i++){
if(i==pos){
digitalWrite(FndSelectPin[i], LOW);
}
else{
digitalWrite(FndSelectPin[i], HIGH);
}
}
}
void FndDisplay(int pos, int num){
int i;
int flag = 0;
int shift = 0x01;
FndSelect(pos);
for(i=0; i<8; i++){
flag = (FndFont[num] & shift);
digitalWrite(FndPin[i], flag);
shift << 1;
}
}
void FndTask(void* arg){
int i;
while(1){
for(i=0; i<FND_SIZE; i++){
delay(3);
FndDisplay(i, Fnd[i]);
}
}
}
void setup(){
int i;
for(i=0; i<6; i++){
pinMode(FndSelectPin[i], OUTPUT);
}
for(i=0; i<8; i++){
pinMode(FndPin[i], OUTPUT);
}
for(i=0; i<4; i++){
pinMode(FndPin[i], INPUT);
}
attachInterrupt( 0, KeypadControl1, RISING );
attachInterrupt( 1, KeypadControl2, RISING );
attachInterrupt( 2, KeypadControl3, RISING );
attachInterrupt( 3, KeypadControl4, RISING );
vSemaphoreCreateBinary(sem1);
xTaskCreate(KeypadTask, NULL, 200, NULL, 2, NULL);
xTaskCreate(FndTask, NULL, 200, NULL, 1, NULL);
vTaskStartScheduler();
}
void loop(){}
세마포어 기반 Keypad를 이용한 모터 제어
- 왼쪽 회전, 정지, 오른쪽 회전 3개 키에 의해 모터 동작
- Keypad ISR과 Motor Task간 전역변수와 semaphore를 이용해 데이터 전달
#include <FreeRTOS_AVR.h>
#define MS2TICKS(ms) (ms / portTICK_PERIOD_MS)
#define FND_SIZE 6
#define MAX_BUF 2
const int Keypad[3] = { 2, 3, 21 };
const int MT_P = 10;
const int MT_N = 9;
SemaphoreHandle_t emptySem;
SemaphoreHandle_t fullSem;
SemaphoreHandle_t mutexSem;
typedef struct {
int SendValue[MAX_BUF];
int in;
int out;
int counter;
} BufferType;
BufferType buf;
int MotorValue = 0;
void SetMotor(int value) {
Serial.print("SET Motor");
Serial.println(value);
MotorValue = value;
}
void KeypadControl1() {
xSemaphoreTake(emptySem, portMAX_DELAY);
xSemaphoreTake(mutexSem, portMAX_DELAY);
buf.SendValue[buf.in] = 1;
buf.in = (buf.in + 1) % MAX_BUF;
buf.counter++;
xSemaphoreGive(mutexSem);
xSemaphoreGive(fullSem);
}
void KeypadControl2() {
xSemaphoreTake(emptySem, portMAX_DELAY);
xSemaphoreTake(mutexSem, portMAX_DELAY);
buf.SendValue[buf.in] = 2;
buf.in = (buf.in + 1) % MAX_BUF;
buf.counter++;
xSemaphoreGive(mutexSem);
xSemaphoreGive(fullSem);
}
void KeypadControl3() {
xSemaphoreTake(emptySem, portMAX_DELAY);
xSemaphoreTake(mutexSem, portMAX_DELAY);
buf.SendValue[buf.in] = 3;
buf.in = (buf.in + 1) % MAX_BUF;
buf.counter++;
xSemaphoreGive(mutexSem);
xSemaphoreGive(fullSem);
}
void KeypadTask( void* arg ) {
int keypad;
while(1) {
xSemaphoreTake(fullSem, portMAX_DELAY);
xSemaphoreTake(mutexSem, portMAX_DELAY);
keypad = buf.SendValue[buf.out];
buf.out = (buf.out + 1) % MAX_BUF;
buf.counter--;
SetMotor(keypad);
xSemaphoreGive(mutexSem);
xSemaphoreGive(emptySem);
}
}
void MotorTask( void* arg) {
while(1) {
if(MotorValue == 1) {
digitalWrite(MT_P, LOW);
digitalWrite(MT_N, HIGH);
}
else if(MotorValue == 2) {
digitalWrite(MT_P, LOW);
digitalWrite(MT_N, LOW);
}
else if(MotorValue == 3) {
digitalWrite(MT_P, HIGH);
digitalWrite(MT_N, LOW);
}
}
}
void setup() {
int i;
Serial.begin(9600);
pinMode(MT_P, OUTPUT);
pinMode(MT_N, OUTPUT);
for( i = 0; i < 3; i++ ) {
pinMode( Keypad[ i ], INPUT );
}
attachInterrupt( 0, KeypadControl1, RISING );
attachInterrupt( 1, KeypadControl2, RISING );
attachInterrupt( 2, KeypadControl3, RISING );
vSemaphoreCreateBinary(emptySem);
vSemaphoreCreateBinary(fullSem);
vSemaphoreCreateBinary(mutexSem);
xTaskCreate( KeypadTask, NULL, 200, NULL, 2, NULL );
xTaskCreate( MotorTask, NULL, 200, NULL, 1, NULL );
vTaskStartScheduler();
}
void loop() {
}