Cortex-M 3(NXP LPC 1788)のUART用法
6057 ワード
仕事の中でよくプラットフォームのシリアルポートとPC機を接続して、シリアルポートを通じて情報を印刷してプログラムのデバッグを行います.LPC 1788には5つのシリアルポートUart 0~Uart 4があり、開発ボードのリソースとともに、Uart 2を使用して簡単なシリアルポート出力と入力中断の操作を行う.UART 2のRXDおよびTXDは、開発ボード上で74 HC 4052マルチスイッチを用いて選択され、SP 3243 Eを用いて3.0 Vから5.5 VへのRS−232レベル変換が行われる.マニュアルを見て関連するジャンプキャップを配置し、DBポートのシリアルポート出力がUart 2であることを保証します.
Uart関連システム構成とUartモジュールの構成について説明します.UartのクロックはPCLKを採用し,我々はシステムのCCLKを120 M,PCLKを60 Mとし,後にシリアルポートを設けたボーレートはPLCKを用いて計算した.シリアルポート2の機能を使用するには、PCONPをシステムクロックで制御し、GPIOピンをUart 2とするRXDおよびTXD機能を構成する必要がある.通信を実現するには、伝送されるボーレート、データ長、ストップビット、チェックなど、データのフォーマットを設定する必要があります.これらのデータは、線形制御レジスタUnLCRで制御されます.ボーレートの生成には分数ボーレート分周器UnFDRと主分周器DLL,DLMを通過する必要がある.カウント式は下図の通りです.
計算によると、PLCK=60 M、ボーレート115200、データビット8、停止ビット1、チェックなしの場合、DLL=22、DLM=0、DivAddVal=1、MulVal=2、リニアコントロールレジスタの値は0 x 3となる.
シリアルポートを介してデータを送信する場合、送信するデータを送信保持レジスタUnTHRに書き込むだけで、システムはシフトレジスタを介してデータをシリアルポートを介して送信する.システムの送信状態を知るためには、リニアステートレジスタUnLSRも必要であり、例えば、プログラムではこのレジスタの5番目のビットを用いて保持レジスタが空であるか否かを判定し、データオーバーフローを防止する.
シリアルポートの割り込み操作が必要な場合は、シリアルポート割り込みイネーブルレジスタUnIERやシリアルポート割り込み識別レジスタUnIIRなどのシリアルポート割り込みを構成する必要がある.プログラムではシリアルポート2の受信割り込みを用いているため、割り込み可能設定レジスタISERでUART 2を割り込み、シリアルポート割り込み可能レジスタUnIERではシリアルポートの受信を割り込み、この割り込みは同時に文字受信タイムアウト割り込みを可能にする.UART 2のRXDピンが受信したデータはFIFOに格納され、プログラムでは受信FIFOのトリガ条件が1バイト、すなわち受信データがあればトリガするように構成されている.割り込みトリガ後,割り込み識別レジスタUnIIRに基づいてシリアルポートの受信割り込み,タイムアウト割り込み,送信割り込みなどを判断できる.割り込みに入ると,受信割り込みとタイムアウト割り込みは,いずれも受信キャッシュレジスタUnRBRを読み出して割り込みリセットを行い,次の割り込みを発生させることができる.
以下のプログラム例では、プログラムがメニューの印刷を開始し、PCシリアルポートソフトウェアが開発ボードに1バイトのデータを送信し、開発ボードがデータを受信した後にUnRBRを読み出す前後の割り込み識別レジスタIIRの値と、受信した値をPCに返信する.0 x 5 aまたは0 xa 5であれば、LEDランプをオンまたはオフにすることもできます.
運転結果を下図に示す
シリアルデバッグソフトウェアのダウンロードをクリックしてダウンロードします
Uart関連システム構成とUartモジュールの構成について説明します.UartのクロックはPCLKを採用し,我々はシステムのCCLKを120 M,PCLKを60 Mとし,後にシリアルポートを設けたボーレートはPLCKを用いて計算した.シリアルポート2の機能を使用するには、PCONPをシステムクロックで制御し、GPIOピンをUart 2とするRXDおよびTXD機能を構成する必要がある.通信を実現するには、伝送されるボーレート、データ長、ストップビット、チェックなど、データのフォーマットを設定する必要があります.これらのデータは、線形制御レジスタUnLCRで制御されます.ボーレートの生成には分数ボーレート分周器UnFDRと主分周器DLL,DLMを通過する必要がある.カウント式は下図の通りです.
計算によると、PLCK=60 M、ボーレート115200、データビット8、停止ビット1、チェックなしの場合、DLL=22、DLM=0、DivAddVal=1、MulVal=2、リニアコントロールレジスタの値は0 x 3となる.
シリアルポートを介してデータを送信する場合、送信するデータを送信保持レジスタUnTHRに書き込むだけで、システムはシフトレジスタを介してデータをシリアルポートを介して送信する.システムの送信状態を知るためには、リニアステートレジスタUnLSRも必要であり、例えば、プログラムではこのレジスタの5番目のビットを用いて保持レジスタが空であるか否かを判定し、データオーバーフローを防止する.
シリアルポートの割り込み操作が必要な場合は、シリアルポート割り込みイネーブルレジスタUnIERやシリアルポート割り込み識別レジスタUnIIRなどのシリアルポート割り込みを構成する必要がある.プログラムではシリアルポート2の受信割り込みを用いているため、割り込み可能設定レジスタISERでUART 2を割り込み、シリアルポート割り込み可能レジスタUnIERではシリアルポートの受信を割り込み、この割り込みは同時に文字受信タイムアウト割り込みを可能にする.UART 2のRXDピンが受信したデータはFIFOに格納され、プログラムでは受信FIFOのトリガ条件が1バイト、すなわち受信データがあればトリガするように構成されている.割り込みトリガ後,割り込み識別レジスタUnIIRに基づいてシリアルポートの受信割り込み,タイムアウト割り込み,送信割り込みなどを判断できる.割り込みに入ると,受信割り込みとタイムアウト割り込みは,いずれも受信キャッシュレジスタUnRBRを読み出して割り込みリセットを行い,次の割り込みを発生させることができる.
以下のプログラム例では、プログラムがメニューの印刷を開始し、PCシリアルポートソフトウェアが開発ボードに1バイトのデータを送信し、開発ボードがデータを受信した後にUnRBRを読み出す前後の割り込み識別レジスタIIRの値と、受信した値をPCに返信する.0 x 5 aまたは0 xa 5であれば、LEDランプをオンまたはオフにすることもできます.
#define CCLK 120000000
#define PCLK 60000000
#define rFIO1DIR (*(volatile unsigned*)(0x20098020))
#define rFIO1MASK (*(volatile unsigned*)(0x20098030))
#define rFIO1PIN (*(volatile unsigned*)(0x20098034))
#define rFIO1SET (*(volatile unsigned*)(0x20098038))
#define rFIO1CLR (*(volatile unsigned*)(0x2009803c))
#define rISER0 (*(volatile unsigned*)(0xE000E100))
#define rCLKSRCSEL (*(volatile unsigned *)(0x400FC10C)) //
#define rPLL0CON (*(volatile unsigned *)(0x400FC080)) //PLL0
#define rPLL0CFG (*(volatile unsigned *)(0x400FC084)) //PLL0
#define rPLL0STAT (*(volatile unsigned *)(0x400FC088)) //PLL0
#define rPLL0FEED (*(volatile unsigned *)(0x400FC08C)) //PLL0
#define rPLL1CON (*(volatile unsigned *)(0x400FC0A0))
#define rPLL1CFG (*(volatile unsigned *)(0x400FC0A4))
#define rPLL1STAT (*(volatile unsigned *)(0x400FC0A8))
#define rPLL1FEED (*(volatile unsigned *)(0x400FC0AC))
#define rCCLKSEL (*(volatile unsigned *)(0x400FC104)) //CPU
#define rUSBCLKSEL (*(volatile unsigned *)(0x400FC108)) //USB
#define rPCLKSEL (*(volatile unsigned *)(0x400FC1A8)) //
#define rPCON (*(volatile unsigned *)(0x400FC0C0))
#define rPXCONP (*(volatile unsigned *)(0x400FC0C4))
#define rSCS (*(volatile unsigned *)(0x400FC1A0)) //
#define rCLKOUTCFG (*(volatile unsigned *)(0x400FC1C8))
#define rIOCON_P0_10 (*(volatile unsigned *)(0x4002C028))
#define rIOCON_P0_11 (*(volatile unsigned *)(0x4002C02C))
#define rPCONP (*(volatile unsigned *)(0x400FC0C4))
#define rU2LCR (*(volatile unsigned *)(0x4009800C))
#define rU2FDR (*(volatile unsigned *)(0x40098028))
#define rU2DLL (*(volatile unsigned *)(0x40098000))
#define rU2DLM (*(volatile unsigned *)(0x40098004))
#define rU2TER (*(volatile unsigned *)(0x40098030))
#define rU2THR (*(volatile unsigned *)(0x40098000))
#define rU2RBR (*(volatile unsigned *)(0x40098000))
#define rU2FCR (*(volatile unsigned *)(0x40098008))
#define rU2IIR (*(volatile unsigned *)(0x40098008))
#define rU2LSR (*(volatile unsigned *)(0x40098014))
#define rU2IER (*(volatile unsigned *)(0x40098004))
#define rU2ACR (*(volatile unsigned *)(0x40098020))
void UART2_IRQHandler()
{
unsigned int intId;
char tmp_char;
intId = rU2IIR&0xf;
rU2THR = intId;
if(intId == 0xc || intId == 0x4) //RDA CTI
{
rU2LCR &= ~(0x1<<7); //DLAB=0
tmp_char = rU2RBR&0xff;
rU2THR = tmp_char;
}
intId = rU2IIR&0xf;
rU2THR = intId;
if(tmp_char == 0xa5)
rFIO1PIN |= (1<<18);
else if(tmp_char == 0x5a)
rFIO1PIN &= ~(1<<18);
}
void SystemInit()
{
rSCS &= ~(0x1<<4); // 12M
rSCS |= (0x1<<5); //
while(0 == (rSCS & (0x1<<6)));//
rCLKSRCSEL = 0x1;
rPLL0CFG = 0x9; // CCLK = 120M
rPLL0CON = 0x01;
rPLL0FEED = 0xAA;
rPLL0FEED =0x55;
while(0 == (rPLL0STAT & (0x1<<10)));
rCCLKSEL = (0x1 | (0x1<<8));
rPCLKSEL = 0x2; // PCLK = 60M
rCLKOUTCFG = 0x0 | (0xb<<4) | (0x1<<8);
}
void Init_Uart2()
{
rPCONP |= 0x1<<24; // UART2
rIOCON_P0_10 = (rIOCON_P0_10 & (~0x7)) | 0x1; //P0.10 P0.11 UART2
rIOCON_P0_11 = (rIOCON_P0_11 & (~0x7)) | 0x1;
rU2LCR |= 0x1<<7; //DLAB=1
rU2FDR = 1 | 2<<4; // 115200
rU2DLM = 0;
rU2DLL = 22;
rU2LCR &= ~(0x1<<7); //DLAB=0
rU2LCR |= 0x3; //8 , ,1
rU2TER |= 0x1<<7; // 2
rU2IER |= 0x1; // 2
rU2FCR |= 0x1; // FIFO, 1
rU2FCR |= 0x1<<1 | 0x1<<2;
rISER0 |= 0x1<<7; // 2
}
void Uart2SendC(char c)
{
rU2THR = c & 0xff;
while(!(rU2LSR&(0x1<<5))); // rU2THR ,
}
void Uart2SendS(char *s)
{
while(*s)
{
Uart2SendC(*s);
s++;
}
}
int main(void)
{
char str[] = {"
\r1, Display the U2IIR[3:0] + Data + U2IIR[3:0]
\r2, Send 0x5a ---> Turn on the LED
\r3, Send 0xa5 --->Turn off the LED
\r"};
rFIO1DIR |= (1<<18); //GPIO1.18 -> OUTPUT
Init_Uart2();
Uart2SendS(str);
while(1);
}
運転結果を下図に示す
シリアルデバッグソフトウェアのダウンロードをクリックしてダウンロードします