problem statement :
Design and implement a real-time embedded system for the LPC17xx microcontroller to monitor temperature using an ADC, control an LED and motor based on temperature readings, and communicate data over UART. Utilize RTX for task scheduling to manage concurrent tasks, including ADC reading, LED control, motor control, and UART communication. Ensure accurate temperature conversion and periodic data transmission for external monitoring.
Code
#include "LPC17xx.h"
#include <stdio.h>
#include <string.h>
#include "RTL.h" // For RTX (Real-Time eXecutive)
// Constants and Definitions
#define MAX_ADC_VALUE 4095
#define ADC_REF_VOLTAGE 3.3
#define TEMP_SENSOR_OFFSET 0.5 // Voltage offset for LM35 in volts
#define TEMP_SENSOR_SCALE 100.0 // Scale factor for LM35 (10mV per degree)
// Function Prototypes
void initClocks(void);
void initUART0(void);
void UOWrite(char data);
void Send_String(char *StringPtr);
void ADC_Init(void);
unsigned int ADC_GetAdcReading(void);
void GPIO_Init(void);
void TurnOnLED(void);
void TurnOffLED(void);
void TurnOnMotor(void);
void TurnOffMotor(void);
// Global Variables (Shared Between Tasks)
float temperature = 0.0; // Shared variable for temperature
unsigned int adcValue = 0; // Shared variable for ADC value
char tempStr[40]; // Shared buffer for UART messages
// Task Function Prototypes
__task void Task_ADC(void);
__task void Task_LED_Control(void);
__task void Task_Motor_Control(void);
__task void Task_UART(void);
__task void Task_Init(void);
// Task Definitions
__task void Task_Init(void) {
// Initialize hardware peripherals
initClocks();
initUART0();
ADC_Init();
GPIO_Init();
// Create other tasks
os_tsk_create(Task_ADC, 1); // Priority 1
os_tsk_create(Task_LED_Control, 2); // Priority 2
os_tsk_create(Task_Motor_Control, 3); // Priority 3
os_tsk_create(Task_UART, 4); // Priority 4
os_tsk_delete_self(); // Delete Init task after setup
}
__task void Task_ADC(void) {
float voltage;
while (1) {
adcValue = ADC_GetAdcReading();
voltage = ((adcValue / (float)MAX_ADC_VALUE) * ADC_REF_VOLTAGE);
temperature = (voltage - TEMP_SENSOR_OFFSET) * TEMP_SENSOR_SCALE;
os_dly_wait(10); // Delay for 100 ticks
}
}
__task void Task_LED_Control(void) {
while (1) {
if (temperature > 30.0) {
TurnOnLED();
} else {
TurnOffLED();
}
os_dly_wait(10); // Delay to reduce CPU usage
}
}
__task void Task_Motor_Control(void) {
while (1) {
if (temperature > 35.0) {
TurnOnMotor();
} else {
TurnOffMotor();
}
os_dly_wait(10); // Delay to reduce CPU usage
}
}
__task void Task_UART(void) {
while (1) {
sprintf(tempStr, "ADC: %u, Voltage: %.2f V, Temperature: %.2f C\r\n", adcValue,
((adcValue / (float)MAX_ADC_VALUE) * ADC_REF_VOLTAGE), temperature);
Send_String(tempStr);
os_dly_wait(30); // Delay for 300 ticks
}
}
// Helper Functions
void initClocks(void) {
LPC_SC->CLKSRCSEL = 0x01; // Select main oscillator
LPC_SC->PLL0CFG = (24 << 0) | (1 << 16); // M = 25, N = 2
LPC_SC->PLL0CON = 0x01; // Enable PLL
LPC_SC->PLL0FEED = 0xAA;
LPC_SC->PLL0FEED = 0x55;
while (!(LPC_SC->PLL0STAT & (1 << 26))); // Wait for lock
LPC_SC->PLL0CON = 0x03; // Connect PLL
LPC_SC->PLL0FEED = 0xAA;
LPC_SC->PLL0FEED = 0x55;
LPC_SC->CCLKCFG = 0x03; // CCLK = 100 MHz
}
void initUART0(void) {
LPC_PINCON->PINSEL0 |= (1 << 4) | (1 << 6); // Configure P0.2 as TXD0 and P0.3 as RXD0
LPC_UART0->LCR = 0x83; // 8-bit data, no parity, 1 stop bit, DLAB = 1
LPC_UART0->DLM = 0x00;
LPC_UART0->DLL = 0x75; // Set baud rate
LPC_UART0->FDR = 0x10; // Fractional divider not used
LPC_UART0->LCR &= ~(1 << 7); // DLAB = 0
}
void UOWrite(char data) {
while (!(LPC_UART0->LSR & (1 << 5))); // Wait for TX FIFO to be empty
LPC_UART0->THR = data;
}
void Send_String(char *StringPtr) {
while (*StringPtr != '\0') {
UOWrite(*StringPtr);
StringPtr++;
}
}
void ADC_Init(void) {
LPC_PINCON->PINSEL1 |= (1 << 18); // Configure P0.24 as AD0.1
LPC_ADC->ADCR = (1 << 1) | // Select AD0.1
(4 << 8) | // CLKDIV = 4
(1 << 21); // Enable ADC
}
unsigned int ADC_GetAdcReading(void) {
LPC_ADC->ADCR |= (1 << 24); // Start conversion
while (!(LPC_ADC->ADDR1 & (1U << 31))); // Wait for completion
return (LPC_ADC->ADDR1 >> 4) & 0xFFF; // Return 12-bit ADC result
}
void GPIO_Init(void) {
LPC_GPIO0->FIODIR |= (1 << 22) | (1 << 24); // P0.22 (LED) and P0.24 (Motor) as output
}
void TurnOnLED(void) {
LPC_GPIO0->FIOSET = (1 << 22); // Turn on LED (P0.22)
}
void TurnOffLED(void) {
LPC_GPIO0->FIOCLR = (1 << 22); // Turn off LED (P0.22)
}
void TurnOnMotor(void) {
LPC_GPIO0->FIOSET = (1 << 24); // Turn on Motor (P0.24)
}
void TurnOffMotor(void) {
LPC_GPIO0->FIOCLR = (1 << 24); // Turn off Motor (P0.24)
}
// Main Function
int main(void) {
os_sys_init(Task_Init); // Start the RTOS with the Init task
while (1); // Infinite loop (should never reach here)
}
Output result :
Concluconclusion :
This code represents a comprehensive solution for monitoring temperature and controlling an LED and motor based on the temperature readings using the LPC17xx microcontroller. By leveraging the RTX real-time operating system, the code ensures efficient task management and concurrency, enabling the system to perform ADC readings, control peripherals, and communicate data over UART seamlessly. The result is a well-organized, responsive embedded system capable of real-time monitoring and control, highlighting the power of combining hardware and software for effective embedded applications.