lOMoARcPSD|1 6072870
TH6.1: Sử dụng Mailbox
#include <Arduino.h>
#include <Arduino_FreeRTOS.h>
#include <queue.h>
// Khai o queue handle
QueueHandle_t myQueue;
// Định nghĩa một cấ´u trúc dữ liệu đơn gia‘n cho Mailbox
typedef struct {
int id;
char message[20];
} Mailbox;
// Tác vụ gử‘i dữ liệu
void senderTask(void *pvParameters)
{(void) pvParameters;
Mailbox mailbox;
int count = 0;
while (1)
{ mailbox.id =
count;
snprintf(mailbox.message, sizeof(mailbox.message), "Message %d",count);
// Gử‘i dữ liệu vào queue
xQueueSend(myQueue, &mailbox, portMAX_DELAY);
count++;
vTaskDelay(1000 / portTICK_PERIOD_MS); // Delay 1 giấy
}
}
// Tác vụ nhận dữ liệu
void receiverTask(void *pvParameters)
{(void) pvParameters;
Mailbox mailbox;
while (1) {
// Nhận d liệu t queue
if (xQueueReceive(myQueue, &mailbox, portMAX_DELAY) == pdPASS) {
Serial.print("Received: ID = ");
Serial.print(mailbox.id);
Serial.print(", Message = ");
Serial.println(mailbox.message);
}
}
}
void setup() {
Serial.begin(9600);
lOMoARcPSD|1 6072870
// Tạo queue
myQueue = xQueueCreate(10, sizeof(Mailbox));
if (myQueue == NULL) {
Serial.println("Queue creation failed!");
while (1); // Dừng chửơng trình nế´u tạo queue thấ´t bại
}
// Tạo các task
xTaskCreate(senderTask, "Sender", 256, NULL, 1, NULL);
xTaskCreate(receiverTask, "Receiver", 256, NULL, 1, NULL);
// Bắ´t đấ`u scheduler
vTaskStartScheduler();
}
void loop() {
// Không cấ`n sử‘dụng loop() trong FreeRTOS
}
TH6.2: Sử dụng Event Group:
// Bao gô`m các header file cu‘a FreeRTOS event groups
#include <Arduino_FreeRTOS.h>
#include "event_groups.h"
// Định nghĩa ba biế´n cờ sự kiện (event flag bit)
#define TASK1_BIT (1UL << 0UL) // Dịch bit 0
#define TASK2_BIT (1UL << 1UL) // Dịch bit 1
#define TASK3_BIT (1UL << 2UL) // Dịch bit 2
// Khai báo biế´n handler cho event group
EventGroupHandle_t xEventGroup;
// Hằng sô´đế‘định nghĩa độ trế'500ms
// chúng ta sẽ sử‘dụng đế‘thực hiện định kỳ mô'i task
// sau mô'i 500ms
const TickType_t xDelay500ms = pdMS_TO_TICKS(500);
void setup()
{
// Khơi tạo module UART với baud rate 9600
Serial.begin(9600);
// Tạo event group gán vào handler đã tạo trửớc đó
xEventGroup = xEventGroupCreate();
// Tạo ba tác vụ đửợc sử‘dụng đế‘kích hoạt sự kiện
// với sự trợ giúp cu‘a các cờ sự kiện đã định nghĩa ơ trến
xTaskCreate(InputTask1, "Input Task 1", 100, NULL, 1, NULL);
xTaskCreate(InputTask2, "Input Task 2", 100, NULL, 1, NULL);
lOMoARcPSD|1 6072870
xTaskCreate(InputTask3, "Input Task 3", 100, NULL, 1, NULL);
// Tạo tác vụ đấ`u ra sẽ chỉ thực hiện khi ca ba sự kiện xa‘y ra
xTaskCreate(OutputTask, "Output Task", 100, NULL, 1, NULL);
}
// Định nghĩa cu‘a input task 1
void InputTask1(void *pvParameters)
{
while(1)
{
// Đặt cờ bit TASK1_BIT
xEventGroupSetBits(xEventGroup, TASK1_BIT);
// Trì hoãn tác vụ này trong 500ms
vTaskDelay(xDelay500ms);
}
}
// Định nghĩa cu‘a input task 2
void InputTask2(void *pvParameters)
{
while(1)
{
// Đặt cờ bit TASK2_BIT
xEventGroupSetBits(xEventGroup, TASK2_BIT);
// Trì hoãn tác vụ này trong 500ms
vTaskDelay(xDelay500ms);
}
}
// Định nghĩa cu‘a input task 3
void InputTask3(void *pvParameters)
{
while(1)
{
// Đặt cờ bit TASK3_BIT
xEventGroupSetBits(xEventGroup, TASK3_BIT);
// Trì hoãn tác vụ này trong 500ms
vTaskDelay(xDelay500ms);
}
}
// Định nghĩa cu‘a output task
void OutputTask(void *pvParameters)
{
// Định nghĩa một biế´n giữ trạng thái cu‘a các sự kiện
const EventBits_t xBitsToWaitFor = (TASK1_BIT | TASK2_BIT | TASK3_BIT);
EventBits_t xEventGroupValue;
while(1)
{
xEventGroupValue = xEventGroupWaitBits(xEventGroup,
lOMoARcPSD|1 6072870
if((xEventGroupValue & TASK1_BIT) != 0)
{
xBitsToWaitFor,
pdTRUE,
pdTRUE,
portMAX_DELAY
);
Serial.println("Task1 event occurred");
}
if((xEventGroupValue & TASK2_BIT) != 0)
{
Serial.println("Task2 event occurred");
}
if((xEventGroupValue & TASK3_BIT) != 0)
{
Serial.println("Task3 event occurred");
}
}
}
void loop(){}
TH6.3: Sử dụng Queue
#include <Arduino.h>
#include <Arduino_FreeRTOS.h>
#include <queue.h>
// Định nghĩa sô´chấn cho c đèn LED
#define LED_PIN_8 8
#define LED_PIN_9 9
// Định nghĩa handle cho queue
QueueHandle_t myQueue;
// Nguyến mấ'u các task
void senderTask(void *pvParameters);
void receiverTask(void *pvParameters);
void setup() {
Serial.begin(9600);
// Khơi tạo các chấn LED
pinMode(LED_PIN_8, OUTPUT);
pinMode(LED_PIN_9, OUTPUT);
digitalWrite(LED_PIN_8, HIGH); // Bật LED 8
digitalWrite(LED_PIN_9, LOW); // Tắ´t LED 9
lOMoARcPSD|1 6072870
// Tạo queue
myQueue = xQueueCreate(10, sizeof(int));
// Tạo các task gử‘i nhận
xTaskCreate(senderTask, "Sender Task", 128, NULL, 1, NULL);
xTaskCreate(receiverTask, "Receiver Task", 128, NULL, 2, NULL);
}
void loop() {
// Trô´ng tấ´t ca các task đế`u chạy trong FreeRTOS
}
// Hàm task gử‘i
void senderTask(void *pvParameters) {(void)pvParameters;
int data = 0;
while (1) {
// Gử‘i dữ liệu vào queue xQueueSend(myQueue,
&data, portMAX_DELAY);
// Tắng giá trị cu‘a data
data++;
// Trì hoãn 1 giấy
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
// Hàm task nhận
void receiverTask(void *pvParameters)
{(void)pvParameters;
int receivedData;
while (1) {
// Nhận d liệu t queue
if (xQueueReceive(myQueue, &receivedData, pdMS_TO_TICKS(500)) ==pdPASS)
{
// Kiế‘m tra nế´u receivedData nằm trong khoa‘ng từ 4 đế´n 10
if (receivedData >= 4 && receivedData <= 10) {
digitalWrite(LED_PIN_8, LOW); // Tắ´t LED 8
digitalWrite(LED_PIN_9, HIGH); // Bật LED 9
Serial.println("LED 8 TẮ´T, LED 9 BẬT");
} else {
digitalWrite(LED_PIN_8, HIGH); // Bật LED 8
digitalWrite(LED_PIN_9, LOW); // Tắ´t LED 9
Serial.println("LED 8 BẬT, LED 9 TẮ´T");
}
lOMoARcPSD|1 6072870
} else {
// Chờ 1 giấy nế´u không nhận đửợc dữ liệu
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
}
TH6.4: Sử dụng Queue
#include <Arduino_FreeRTOS.h>
#include <queue.h>
#include <LiquidCrystal.h> // Bao gô`m thử viện LCD
// Khơi tạo đô´i tửợng LCD với các chấn RS, E, D4, D5, D6, D7
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
// Khai o handle cho queue
QueueHandle_t xQueue;
void setup()
{
Serial.begin(9600); // Khơi tạo giao tiế´p Serial với baud rate 9600
lcd.begin(16, 2); // Khơi tạo LCD với 16 cột 2 hàng
// Tạo queue thế‘chứa tô´i đa 5 phấ`n tử‘kiế‘u int
xQueue = xQueueCreate(5, sizeof(int));
if (xQueue != NULL) { // Kiế‘m tra xem queue đửợc tạo thành công hay
không
// Tạo task AdcTask với tến "Sender", ngắn xế´p 240 từ, ửu tiến 1
xTaskCreate(AdcTask, "Sender", 240, NULL, 1, NULL);
// Tạo task LcdTask với tến "Receiver", ngắn xế´p 240 từ, ửu tiến 2
xTaskCreate(LcdTask, "Receiver", 240, NULL, 2, NULL);
// Bắ´t đấ`u scheduler cu‘a FreeRTOS
vTaskStartScheduler();
} else {
// Nế´u không thế‘tạo queue, thực hiện xử‘lý lô'i ơ
}
}
đấy
void loop()
{
// Hàm loop đế‘trô´ng tấ´t ca các tác vụ đế`u chạy trong FreeRTOS
}
void AdcTask(void *pvParameters)
{
for (;;) // Vòng lặp vô tận cho task
{
lOMoARcPSD|1 6072870
int adc_value; // Khai báo biế´n đế‘lửu giá trị ADC
adc_value = analogRead(A4); // Đọc giá trị từ chấn analog A4
xQueueSend(xQueue, &adc_value, portMAX_DELAY); // Gử‘i giá trị ADC vào
queue, chờ mãi mãi nế´u queue đấ`y
Serial.print("AdcTask = "); // In giá tr ADC lến Serial Monitor
Serial.println(adc_value);
//vTaskDelay(100); // Bo comment này nế´u cấ`n trì hoãn
}
}
void LcdTask(void *pvParameters)
{
int ReceivedValue = 0; // Khai báo biế´n đế‘lửu giá trị nhận đửợc từ
queue
for (;;) // Vòng lặp vô tận cho task
{
// Nhận giá trị từ queue, chờ mãi mãi nế´u queue rô'ng
if (xQueueReceive(xQueue, &ReceivedValue, portMAX_DELAY) == pdPASS) {
Serial.print("Received = "); // In giá tr nhận đửợc lến Serial
Monitor
Serial.println(ReceivedValue);
lcd.clear(); // Xóa màn hình LCD
lcd.setCursor(0, 0); // Đặt con tro ơ vị trí cột 0 hàng 0
lcd.print("ADC : "); // In chuô'i "ADC :" lến LCD
lcd.setCursor(6, 0); // Đặt con tro ơ vị trí cột 6 hàng 0
lcd.print(ReceivedValue); // In giá trị nhận đửợc lến LCD
}
taskYIELD(); // Chuyế‘n đô‘i giữa các task đế‘CPU không bị chiế´m dụng
hoàn toàn
}
}

Preview text:

lOMoARcPSD|16072870 TH6.1: Sử dụng Mailbox #include #include #include // Khai báo queue handle QueueHandle_t myQueue;
// Định nghĩa một cấ´u trúc dữ liệu đơn gia‘n cho Mailbox typedef struct { int id; char message[20]; } Mailbox;
// Tác vụ gử‘i dữ liệu
void senderTask(void *pvParameters) {(void) pvParameters; Mailbox mailbox; int count = 0; while (1) { mailbox.id = count;
snprintf(mailbox.message, sizeof(mailbox.message), "Message %d",count);
// Gử‘i dữ liệu vào queue
xQueueSend(myQueue, &mailbox, portMAX_DELAY); count++;
vTaskDelay(1000 / portTICK_PERIOD_MS); // Delay 1 giấy } }
// Tác vụ nhận dữ liệu
void receiverTask(void *pvParameters) {(void) pvParameters; Mailbox mailbox; while (1) {
// Nhận dữ liệu từ queue
if (xQueueReceive(myQueue, &mailbox, portMAX_DELAY) == pdPASS) {
Serial.print("Received: ID = ");
Serial.print(mailbox.id);
Serial.print(", Message = ");
Serial.println(mailbox.message); } } } void setup() { Serial.begin(9600); lOMoARcPSD|16072870 // Tạo queue
myQueue = xQueueCreate(10, sizeof(Mailbox)); if (myQueue == NULL) {
Serial.println("Queue creation failed!");
while (1); // Dừng chửơng trình nế´u tạo queue thấ´t bại } // Tạo các task
xTaskCreate(senderTask, "Sender", 256, NULL, 1, NULL);
xTaskCreate(receiverTask, "Receiver", 256, NULL, 1, NULL); // Bắ´t đấ`u scheduler vTaskStartScheduler(); } void loop() {
// Không cấ`n sử‘dụng loop() trong FreeRTOS }
TH6.2: Sử dụng Event Group:
// Bao gô`m các header file cu‘a FreeRTOS và event groups #include #include "event_groups.h"
// Định nghĩa ba biế´n cờ sự kiện (event flag bit) #define TASK1_BIT
(1UL << 0UL) // Dịch bit 0 #define TASK2_BIT
(1UL << 1UL) // Dịch bit 1 #define TASK3_BIT
(1UL << 2UL) // Dịch bit 2
// Khai báo biế´n handler cho event group
EventGroupHandle_t xEventGroup;
// Hằng sô´đế‘định nghĩa độ trế'500ms
// vì chúng ta sẽ sử‘dụng đế‘thực hiện định kỳ mô'i task // sau mô'i 500ms
const TickType_t xDelay500ms = pdMS_TO_TICKS(500); void setup()
{ // Kh‘ơi tạo module UART với baud rate là 9600 Serial.begin(9600);
// Tạo event group và gán nó vào handler đã tạo trửớc đó
xEventGroup = xEventGroupCreate();
// Tạo ba tác vụ đửợc sử‘dụng đế‘kích hoạt sự kiện
// với sự trợ giúp cu‘a các cờ sự kiện đã định nghĩa ‘ơ trến
xTaskCreate(InputTask1, "Input Task 1", 100, NULL, 1, NULL);
xTaskCreate(InputTask2, "Input Task 2", 100, NULL, 1, NULL); lOMoARcPSD|16072870
xTaskCreate(InputTask3, "Input Task 3", 100, NULL, 1, NULL);
// Tạo tác vụ đấ`u ra sẽ chỉ‘ thực hiện khi ca‘ ba sự kiện xa‘y ra
xTaskCreate(OutputTask, "Output Task", 100, NULL, 1, NULL); }
// Định nghĩa cu‘a input task 1
void InputTask1(void *pvParameters) { while(1) { // Đặt cờ bit TASK1_BIT
xEventGroupSetBits(xEventGroup, TASK1_BIT);
// Trì hoãn tác vụ này trong 500ms vTaskDelay(xDelay500ms); } }
// Định nghĩa cu‘a input task 2
void InputTask2(void *pvParameters) { while(1) { // Đặt cờ bit TASK2_BIT
xEventGroupSetBits(xEventGroup, TASK2_BIT);
// Trì hoãn tác vụ này trong 500ms vTaskDelay(xDelay500ms); } }
// Định nghĩa cu‘a input task 3
void InputTask3(void *pvParameters) { while(1) { // Đặt cờ bit TASK3_BIT
xEventGroupSetBits(xEventGroup, TASK3_BIT);
// Trì hoãn tác vụ này trong 500ms vTaskDelay(xDelay500ms); } }
// Định nghĩa cu‘a output task
void OutputTask(void *pvParameters)
{ // Định nghĩa một biế´n giữ trạng thái cu‘a các sự kiện
const EventBits_t xBitsToWaitFor = (TASK1_BIT | TASK2_BIT | TASK3_BIT); EventBits_t xEventGroupValue; while(1)
{ xEventGroupValue = xEventGroupWaitBits(xEventGroup, lOMoARcPSD|16072870 xBitsToWaitFor, pdTRUE, pdTRUE, portMAX_DELAY );
if((xEventGroupValue & TASK1_BIT) != 0)
{ Serial.println("Task1 event occurred"); }
if((xEventGroupValue & TASK2_BIT) != 0)
{ Serial.println("Task2 event occurred"); }
if((xEventGroupValue & TASK3_BIT) != 0)
{ Serial.println("Task3 event occurred"); } } } void loop(){} TH6.3: Sử dụng Queue #include #include #include
// Định nghĩa sô´chấn cho các đèn LED #define LED_PIN_8 8 #define LED_PIN_9 9
// Định nghĩa handle cho queue QueueHandle_t myQueue; // Nguyến mấ'u các task
void senderTask(void *pvParameters);
void receiverTask(void *pvParameters); void setup() { Serial.begin(9600);
// Kh‘ơi tạo các chấn LED pinMode(LED_PIN_8, OUTPUT); pinMode(LED_PIN_9, OUTPUT);
digitalWrite(LED_PIN_8, HIGH); // Bật LED 8
digitalWrite(LED_PIN_9, LOW); // Tắ´t LED 9 lOMoARcPSD|16072870 // Tạo queue
myQueue = xQueueCreate(10, sizeof(int));
// Tạo các task gử‘i và nhận
xTaskCreate(senderTask, "Sender Task", 128, NULL, 1, NULL);
xTaskCreate(receiverTask, "Receiver Task", 128, NULL, 2, NULL); } void loop() {
// Trô´ng vì tấ´t ca‘ các task đế`u chạy trong FreeRTOS } // Hàm task gử‘i
void senderTask(void *pvParameters) {(void)pvParameters; int data = 0; while (1) {
// Gử‘i dữ liệu vào queue xQueueSend(myQueue, &data, portMAX_DELAY);
// Tắng giá trị cu‘a data data++; // Trì hoãn 1 giấy
vTaskDelay(pdMS_TO_TICKS(1000)); } } // Hàm task nhận
void receiverTask(void *pvParameters) {(void)pvParameters; int receivedData; while (1) {
// Nhận dữ liệu từ queue
if (xQueueReceive(myQueue, &receivedData, pdMS_TO_TICKS(500)) ==pdPASS) {
// Kiế‘m tra nế´u receivedData nằm trong khoa‘ng từ 4 đế´n 10
if (receivedData >= 4 && receivedData <= 10) {
digitalWrite(LED_PIN_8, LOW); // Tắ´t LED 8
digitalWrite(LED_PIN_9, HIGH); // Bật LED 9
Serial.println("LED 8 TẮ´T, LED 9 BẬT"); } else {
digitalWrite(LED_PIN_8, HIGH); // Bật LED 8
digitalWrite(LED_PIN_9, LOW); // Tắ´t LED 9
Serial.println("LED 8 BẬT, LED 9 TẮ´T"); } lOMoARcPSD|16072870 } else {
// Chờ 1 giấy nế´u không nhận đửợc dữ liệu
vTaskDelay(pdMS_TO_TICKS(1000)); } } } TH6.4: Sử dụng Queue #include #include
#include // Bao gô`m thử viện LCD
// Kh‘ơi tạo đô´i tửợng LCD với các chấn RS, E, D4, D5, D6, D7
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // Khai báo handle cho queue QueueHandle_t xQueue; void setup()
{ Serial.begin(9600); // Kh‘ơi tạo giao tiế´p Serial với baud rate 9600
lcd.begin(16, 2); // Kh‘ơi tạo LCD với 16 cột và 2 hàng
// Tạo queue có thế‘chứa tô´i đa 5 phấ`n tử‘kiế‘u int
xQueue = xQueueCreate(5, sizeof(int));
if (xQueue != NULL) { // Kiế‘m tra xem queue có đửợc tạo thành công hay
không// Tạo task AdcTask với tến "Sender", ngắn xế´p 240 từ, ửu tiến 1
xTaskCreate(AdcTask, "Sender", 240, NULL, 1, NULL);
// Tạo task LcdTask với tến "Receiver", ngắn xế´p 240 từ, ửu tiến 2
xTaskCreate(LcdTask, "Receiver", 240, NULL, 2, NULL);
// Bắ´t đấ`u scheduler cu‘a FreeRTOS vTaskStartScheduler(); } else {
// Nế´u không thế‘tạo queue, thực hiện xử‘lý lô'i ‘ơ đấy } } void loop()
{ // Hàm loop đế‘trô´ng vì tấ´t ca‘ các tác vụ đế`u chạy trong FreeRTOS }
void AdcTask(void *pvParameters)
{ for (;;) // Vòng lặp vô tận cho task { lOMoARcPSD|16072870
int adc_value; // Khai báo biế´n đế‘lửu giá trị ADC
adc_value = analogRead(A4); // Đọc giá trị từ chấn analog A4
xQueueSend(xQueue, &adc_value, portMAX_DELAY); // Gử‘i giá trị ADC vào
queue, chờ mãi mãi nế´u queue đấ`y
Serial.print("AdcTask = "); // In giá trị ADC lến Serial Monitor
Serial.println(adc_value);
//vTaskDelay(100); // Bo‘ comment này nế´u cấ`n trì hoãn } }
void LcdTask(void *pvParameters)
{ int ReceivedValue = 0; // Khai báo biế´n đế‘lửu giá trị nhận đửợc từ queue
for (;;) // Vòng lặp vô tận cho task
{ // Nhận giá trị từ queue, chờ mãi mãi nế´u queue rô'ng
if (xQueueReceive(xQueue, &ReceivedValue, portMAX_DELAY) == pdPASS) {
Serial.print("Received = "); // In giá trị nhận đửợc lến Serial
MonitorSerial.println(ReceivedValue);
lcd.clear(); // Xóa màn hình LCD
lcd.setCursor(0, 0); // Đặt con tro‘ ‘ơ vị trí cột 0 hàng 0
lcd.print("ADC : "); // In chuô'i "ADC :" lến LCD
lcd.setCursor(6, 0); // Đặt con tro‘ ‘ơ vị trí cột 6 hàng 0
lcd.print(ReceivedValue); // In giá trị nhận đửợc lến LCD }
taskYIELD(); // Chuyế‘n đô‘i giữa các task đế‘CPU không bị chiế´m dụng hoàn toàn } }
Document Outline

  • TH6.1: Sử dụng Mailbox
  • TH6.2: Sử dụng Event Group:
  • TH6.3: Sử dụng Queue
  • TH6.4: Sử dụng Queue