خب در آموزش میکروکنترلر LPC1768 رسیدیم به مبحث UART که یکی از کاربردی ترین قسمت های میکروکنترلر هستش و امروزه اکثر ماژول ها با این پروتکل اطلاعات ارسال و دریافت میکنن و همچنین برای ارتباط با کامپیوتر و سیستم های دیگر نیز خیلی مفیده…در ادامه با میکرو دیزاینر الکترونیک باشید تا در این جلسه UART را هم یاد بگیریم.
خب بریم سر برسی UART در LPC1768 ، البته امیدوارم در مورد UART اطلاعاتی داشته باشید اگر هم ندارید مقاله زیر را بخوند:
در میکروکنترلر LPC1768 چهارتا UART داریم که UART 0,2,3 دارای یکسری امکانات اضافی مانند IrDA یا ارتباط مادون قرمز هستش و UART 1 دارای سیگنال های ارتباط با مودم و RS485 هستش که در دیتاشیت هم اینا را جدا برسی کرده و ما در این آموزش مباحث مبتدی را یاد میگریم و در آینده برای مباحث پیشرفته جلسات جداگانه می نویسم.
امکانات کلی واحد های UART
- اندازه داده 5,6,7,8 بیتی
- تولید و چک کردن خودکار Parity با حالت های odd,even,mark,space,none قابل انتخاب
- بیت های توقف یک یا دو بیتی
- رجیستر های FIFO شانزده بایتی برای دریافت و ارسال
- تولید کننده baud rate داخلی
- پشتیبانی ازDMA برای ارسال و دریافت
- قابلیت تنظیم خودکار baud rate
- حالت آدرس دهی چند پردازنده ای
- آشکار ساز و تولید کننده قطع ارتباط
- حالت کنترل جریان نرم افزاری (UART 0,2,3)
- حالت IrDA یا ارتباط با مادون قرمز (UART 0,2,3)
- سیگنال های کنترل مودم (UART 1)
- پشتیبانی از RS485 (UART 1)
مراحل پیکر بندی UART های LPC1768
- فعال کردن تغذیه از رجیستر PCONP ( البته بعد از ریست میکروکنترلر UART0,1 فعال هستن و UART2,3 غیر فعال هستن)
- تنظیم کلا از رجیستر PCLKSEL0
- تنظیم Baud rate
- تنظیم FIFO
- تنظیم پین ها از رجیسترهای PINSELx
- تنظیبم وقفه ها
- تنظیم DMA
پین های UART برای UART0,2,3
RXD0, RXD2, RXD3 Input TXD0, TXD2, TXD3 Output
پین های UART برای UART1
توابع CMSIS برای راه اندازی UART های LPC1768
قبل از معرفی توابع اول بهتره ساختارها یا استراکچر های مورد نیاز این توابع را برسی کنیم. حالا ساختار چیه ؟ ساختار از تجمع چندین متغیر با یک نام را میگن. مثلا یک در اینجا یک ساختار داریم کهع داخلش چندتا متغیر برای تنظیمات مختلف UART ازش استفاده میکنیم.اول به متغیر های داخل ساختار یکی یکی مقدار میدیم و بعد کل ساختار را به تابع میفرستیم تا تنظیمات را ازش بخونه و تنظیم کنه. حالا مثال زیر را ببینید و اگر متوجه تعریف علمی ان هم نشدید مهم نیست فقط متوجه بشید چطوری ازش استفاده میکنم.
متغیر ساختار UART_CFG_Type
خب گفتیم یک نوع متغیر هست مثل CHAR , INT پس اول یک متغیر از نوع UART_CFG_Type تعریف میکنیم:
UART_CFG_Type UARTConfigStruct UART_CFG_Type A;;
نکته : خب در مثال بالا دوتا متغیر تعریف کردیم از نوع ساختار UART_CFG_Type که البته بجای استفاده از اسم A بهتره مثل اولی تعریف کنیم که خوانا تر باشه ولی A را نوشتم تا بگم اون اسم UARTConfigStruct فقط یک اسم متغیر هست. ساختار ما شامل Parity Baud_rate, Databits, Stopbits , هستن که در زیر مقادیری که میتونه داشته باشت اومده :
uint32_t Baud_rate; /**< UART baud rate */ UART_PARITY_Type Parity; /**< Parity selection, should be: - UART_PARITY_NONE: No parity - UART_PARITY_ODD: Odd parity - UART_PARITY_EVEN: Even parity - UART_PARITY_SP_1: Forced "1" stick parity - UART_PARITY_SP_0: Forced "0" stick parity */ UART_DATABIT_Type Databits; /**< Number of data bits, should be: - UART_DATABIT_5: UART 5 bit data mode - UART_DATABIT_6: UART 6 bit data mode - UART_DATABIT_7: UART 7 bit data mode - UART_DATABIT_8: UART 8 bit data mode */ UART_STOPBIT_Type Stopbits; /**< Number of stop bits, should be: - UART_STOPBIT_1: UART 1 Stop Bits Select - UART_STOPBIT_2: UART 2 Stop Bits Select */
خب چطوری به این متغیر ها مقدار بدیم ! به مثال زیر توجه کنید متوجه میشید.
UARTConfigStruct-> Baud_rate= 9600 UARTConfigStruct->Parity= UART_PARITY_NONE UARTConfigStruct->Databits= UART_DATABIT_5 UARTConfigStruct-> Stopbits= UART_STOPBIT_1
تابع UART_ConfigStructInit
خب بعد از اینکه به این متغیر ها مقدار دادیم ساختارمون را پاس میدیم به تابع تا مقادیر را تنظیم کنه:
UART_ConfigStructInit(&UARTConfigStruct);
خب این ساختار را داشته باشید در جاهای دیگه هم استفاده میشه.
- نکته : اگر مقادیر ساختار تنظیم نشه بصورت پیشفرض روی مقادیر زیر تظنیم هستن:
* Baudrate = 9600bps * 8 data bit * 1 Stop bit * None parity
تابع UART_Init
void UART_Init(LPC_UART_TypeDef *UARTx, UART_CFG_Type *UART_ConfigStruct);
این تابع برای پیکربندی و راه اندازی اولیه هستش
- ورودی اول تابع باید یکی از LPC_UART0, LPC_UART1, LPC_UART2, LPC_UART3
- ورودی دوم همون ساختاری است که در بالا توضیح دادم
تابع UART_DeInit
void UART_DeInit(LPC_UART_TypeDef* UARTx);
مقادیر رجیستر ها را برای بعد از ریست تنظیم میکنه
- ورودی تابع باید یکی از LPC_UART0, LPC_UART1, LPC_UART2, LPC_UART3
تابع UART_TxCmd
void UART_TxCmd(LPC_UART_TypeDef *UARTx, FunctionalState NewState);
این تابع برای فعال سازی و غیر فعال سازی ارسال داده UART هستش
- ورودی اول تابع باید یکی از LPC_UART0, LPC_UART1, LPC_UART2, LPC_UART3
- ورودی دوم تابع برای فعال سازی ENABLE و برای غیر فعال سازی DISABLE
تابع UART_SendByte
void UART_SendByte(LPC_UART_TypeDef* UARTx, uint8_t Data);
برای ارسال یک بایت داده از این تابع استفاده میکنیم.
تابع UART_ReceiveByte
uint8_t UART_ReceiveByte(LPC_UART_TypeDef* UARTx);
برای دریافت یک بایت داده از این تابع استفاده میشه.
تابع UART_Send
uint32_t UART_Send(LPC_UART_TypeDef *UARTx, uint8_t *txbuf, uint32_t buflen, TRANSFER_BLOCK_Type flag);
برای ارسال یک رشته بزرگ از این تابع استفاده میکنیم
- ورودی اول تابع باید یکی از LPC_UART0, LPC_UART1, LPC_UART2, LPC_UART3
- ورودی دوم اشاره گر به بافر ارسال هستش
- ورودی سوم طول بافر ارسال هستش
- ورودی چهارم هم میتونه NONE_BLOCKING یا BLOCKING باشه که در حالت BLOCKING یک زمان TIME OUT در نظر گرفته میشه
- خروجی تابع تعداد بایت های ارسالی هست
تابع UART_Receive
uint32_t UART_Receive(LPC_UART_TypeDef *UARTx, uint8_t *rxbuf, uint32_t buflen, TRANSFER_BLOCK_Type flag);
- ورودی اول تابع باید یکی از LPC_UART0, LPC_UART1, LPC_UART2, LPC_UART3
- ورودی دوم اشاره گر به بافر دریافت هستش
- ورودی سوم طول بافر هستش
- ورودی چهارم هم میتونه NONE_BLOCKING یا BLOCKING باشه که در حالت BLOCKING یک زمان TIME OUT در نظر گرفته میشه
- خروجی تابع تعداد بایت های دریافتی هست
تابع UART_IntConfig
void UART_IntConfig(LPC_UART_TypeDef *UARTx, UART_INT_Type UARTIntCfg,FunctionalState NewState);
این تابع برای فعال و غیر و فعال کردن یک وقفه مشخص از UART استفاده میشه
- ورودی اول تابع باید یکی از LPC_UART0, LPC_UART1, LPC_UART2, LPC_UART3
- ورودی دوم نوع وقفه UART هستش که میتونه یکی از حالت زیر باشه :
UART_INTCFG_RBR : RBR Interrupt enable UART_INTCFG_THRE : THR Interrupt enable UART_INTCFG_RLS : RX line status interrupt enable UART1_INTCFG_MS : Modem status interrupt enable (UART1 only) UART1_INTCFG_CTS : CTS1 signal transition interrupt enable (UART1 only) UART_INTCFG_ABEO : Enables the end of auto-baud interrupt UART_INTCFG_ABTO : Enables the auto-baud time-out interrupt
- ورودی سوم تابع برای فعال سازی ENABLE و برای غیر فعال سازی DISABLE
تابع UART_GetIntId
این تابع برای شناسایی منبع وقفه UART مورد استفاده قرار میگیره در حقیقت خروجی این تابع مقدار رجیستر UIIR هستش که برای شناسایی منبع وقفه میتونه یکی از مقادیر زیر باشه :
#define UART_IIR_INTSTAT_PEND /*!<Interrupt Status - Active low */ #define UART_IIR_INTID_RLS /*!<Interrupt identification: Receive line status*/ #define UART_IIR_INTID_RDA /*!<Interrupt identification: Receive data available*/ #define UART_IIR_INTID_CTI /*!<Interrupt identification: Character time-out indicator*/ #define UART_IIR_INTID_THRE /*!<Interrupt identification: THRE interrupt*/ #define UART1_IIR_INTID_MODEM /*!<Interrupt identification: Modem interrupt*/ #define UART_IIR_INTID_MASK /*!<Interrupt identification: Interrupt ID mask */ #define UART_IIR_FIFO_EN /*!<These bits are equivalent to UnFCR[0] */ #define UART_IIR_ABEO_INT /*!< End of auto-baud interrupt */ #define UART_IIR_ABTO_INT /*!< Auto-baud time-out interrupt */
خب تا اینجا توابع مهم را برسی کردیم و البته توابع مهم دیگر در بخش های پیشرفته برسی میشن.
سرویس روتین تابع برای UART
void UART0_IRQHandler(void)
در داخل این تابع میتوانید مقدار منبع وقفه را شناسایی و کار مورد نظر را روی آن انجام دهید.
مثال
#include "inc/lpc17xx.h" #include "inc/lpc17xx_uart.h" #include "inc/lpc17xx_pinsel.h" int main(void){ uint8_t string[] = "\nHello World \nMelec.ir \nReceived_data= "; uint8_t buffer[20],len; // UART Configuration structure variable UART_CFG_Type UARTConfigStruct; // UART FIFO configuration Struct variable UART_FIFO_CFG_Type UARTFIFOConfigStruct; // Pin configuration for UART0 PINSEL_CFG_Type PinCfg; /* * Initialize UART0 pin connect */ PinCfg.Funcnum = 1; PinCfg.OpenDrain = 0; PinCfg.Pinmode = 0; PinCfg.Pinnum = 2; PinCfg.Portnum = 0; PINSEL_ConfigPin(&PinCfg); PinCfg.Pinnum = 3; PINSEL_ConfigPin(&PinCfg); /* Initialize UART Configuration parameter structure to default state: * Baudrate = 9600bps * 8 data bit * 1 Stop bit * None parity */ UART_ConfigStructInit(&UARTConfigStruct); // Initialize UART0 peripheral with given to corresponding parameter UART_Init(LPC_UART0, &UARTConfigStruct); /* Initialize FIFOConfigStruct to default state: * - FIFO_DMAMode = DISABLE * - FIFO_Level = UART_FIFO_TRGLEV0 * - FIFO_ResetRxBuf = ENABLE * - FIFO_ResetTxBuf = ENABLE * - FIFO_State = ENABLE */ UART_FIFOConfigStructInit(&UARTFIFOConfigStruct); // Initialize FIFO for UART0 peripheral UART_FIFOConfig(LPC_UART0, &UARTFIFOConfigStruct); // Enable UART Transmit UART_TxCmd(LPC_UART0, ENABLE); while(1){ len = 0; while (len == 0) { len = UART_Receive(LPC_UART0, buffer,1, NONE_BLOCKING); } UART_Send(LPC_UART0, string, sizeof(string), BLOCKING); UART_Send(LPC_UART0, buffer, sizeof(buffer), BLOCKING); } return 1; }
مثال بالا یک کاراکتر را از UART0 دریافت میکنه و بعد همراه با یکسری نوشته های دیگر ارسال میکنه.
دوستان عزیزم ممنون که با میکرو دیزایر الکترونیک همراه بودید به پایان جلسه دهم رسیدیم ، این جلسه خیلی نوشتم و خیلی از مطالب این بخش موندن که امیدوارم در جلسات آینده بتونم در مورد موارد پیشرفته UART ها بنویسم. ما را هم دعا کنید و جلسه بعدی را هم مطالعه کنید.
اگر این نوشته برایتان مفید بود لطفا کامنت بنویسید.