MM32SPIN2x 電機(jī)專用MCU功能特色——UART模塊Bit9功能
上一章節(jié)中已經(jīng)教大家如何使用MM32SPIN2x的比較器輪詢功能,本章節(jié)將與大家一起配置UART的Bit9模式實(shí)現(xiàn)多機(jī)通訊功能。
圖1UART多機(jī)通信
在雙機(jī)通訊中,UART的8bit通信的第九位一般是奇偶校驗(yàn)位,而多機(jī)通訊中,第九位用于標(biāo)識地址或數(shù)據(jù),常用1表示后面的是從機(jī)地址,0表示后面的是數(shù)據(jù)。我們通常希望只有被尋址的接收者才被激活,來接收隨后的數(shù)據(jù),這樣就可以減少由未被尋址的接收器的參與帶來的多余的UART服務(wù)開銷。未被尋址的設(shè)備可啟用其靜默功能置于靜默模式。在靜默模式里,任何接收狀態(tài)位都不會被設(shè)置,所有接收中斷被禁止。
圖2UART多機(jī)通信
通過 UART 可以實(shí)現(xiàn)多處理器通信 (將幾個 UART 連在一個網(wǎng)絡(luò)里)。例如某個 UART 設(shè)備可以是主,它的 TX 輸出和其他 UART 從設(shè)備的 RX 輸入相連接; UART 從設(shè)備各自的TX 輸出邏輯地與在一起,并且和主設(shè)備的 RX 輸入相連接。
在多處理器配置中,我們通常希望只有被尋址的接收者才被激活,來接收隨后的數(shù)據(jù),這樣就可以減少由未被尋址的接收器的參與帶來的多余的 UART 服務(wù)開銷。
未被尋址的設(shè)備可啟用其靜默功能置于靜默模式。在靜默模式里:
• 任何接收狀態(tài)位都不會被設(shè)置。
• 所有接收中斷被禁止。
• UART_CCR 寄存器中的 RWU 位被置 1。 RWU 可以被硬件自動控制或在某個條件下由軟件寫入。
根據(jù) UART_CCR 寄存器中的 WAKE 位狀態(tài), UART 可以用二種方法進(jìn)入或退出靜默模式。
• 如果 WAKE 位被復(fù)位:進(jìn)行空閑總線檢測。
• 如果 WAKE 位被設(shè)置:進(jìn)行地址標(biāo)記檢測。
今天與大家一起學(xué)習(xí)如何配置使用MM32SPIN2x的UART的Bit9模式實(shí)現(xiàn)多機(jī)通訊功能。
在使能UART_CCR寄存器的B8EN控制位后,UART就會使能9位數(shù)據(jù)的發(fā)送和接收,可以發(fā)送和接收9位數(shù)據(jù)。注意:在 B8EN 使能后,奇偶校驗(yàn)使能位PEN不起作用。
數(shù)據(jù)發(fā)送的時候,在寫入數(shù)據(jù)到發(fā)送寄存器UART_TDR前,需要先設(shè)置B8TXD。B8TXD作為發(fā)送數(shù)據(jù)的MSB和UART_TDR的值同時發(fā)送。如果設(shè)置了B8TOG,如果B8TXD與B8POL相同時,表示該數(shù)據(jù)作為地址幀或者同步幀,發(fā)送結(jié)束后B8TXD會自動翻轉(zhuǎn)。在接下來的數(shù)據(jù)發(fā)送過程中,不需要再設(shè)置B8TXD為無效電平。
數(shù)據(jù)接收的時候,接收數(shù)據(jù)的最高位可以從寄存器位B8RXD讀到。如果接收的B8RXD與B8POL相同時,中斷狀態(tài)寄存器UART_ISR的RXB8_INTF位會置位。
UART9Bit模式的配置步驟如下:
1) 串口時鐘使能,GPIO時鐘使能
2) 串口復(fù)位
3) GPIO端口模式設(shè)置
4) 串口參數(shù)初始化
5)9Bit參數(shù)配置
5) 開啟中斷并且初始化NVIC(可選)
6) 使能串口
7) 編寫中斷處理函數(shù)
程序中配置如下:
voidUart_9Bit_ConfigInit(u32 bound)
{
GPIO_InitTypeDefGPIO_InitStructure;
UART_InitTypeDefUART_InitStructure;
NVIC_InitTypeDefNVIC_InitStruct;
//時鐘使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
//串口復(fù)位及參數(shù)初始化
UART_DeInit(UART1);
UART_InitStructure.UART_BaudRate= bound;
UART_InitStructure.UART_WordLength= UART_WordLength_8b;
UART_InitStructure.UART_StopBits= UART_StopBits_1;
UART_InitStructure.UART_Parity= UART_Parity_No;
UART_InitStructure.UART_HardwareFlowControl=UART_HardwareFlowControl_None;
UART_InitStructure.UART_Mode= UART_Mode_Rx | UART_Mode_Tx;
UART_Init(UART1,&UART_InitStructure);
//開啟中斷并初始化
UART_ClearITPendingBit( UART1, UART_IT_RXIEN);
UART_ITConfig(UART1, UART_IT_RXIEN, ENABLE );
NVIC_InitStruct.NVIC_IRQChannel= UART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd= ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPriority= 0;
NVIC_Init(&NVIC_InitStruct);
//GPIO端口配置
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1);
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//UART 9Bit參數(shù)配置
UART_Enable9bit(UART1,ENABLE);//UART9bit使能控制位
UART_Set9bitPolarity(UART1,UART_9bit_Polarity_High); //第九位高電平有效
UART_WakeUpConfig(UART1,UART_WakeUp_AddressMark);//地址標(biāo)記喚醒
UART_ReceiverWakeUpCmd(UART1,ENABLE);//靜默模式啟用,從機(jī)配置靜默模式,如果作為主機(jī),需要將該句disable
UART_SetRXMASK(UART1,0xFF);//啟用8位地址匹配
UART_SetRXAddress(UART1,0x5A);//地址設(shè)置為0x5A
UART_ITConfig(UART1, UART_IT_RXB8, ENABLE ); //開啟地址幀幀中斷
//使能串口
UART_Cmd(UART1,ENABLE);
}
在上述配置中,我們啟用了地址標(biāo)記喚醒,在接收到的地址幀中的地址與UART_RXADDR中的地址匹配時,UART_CCR中的RWU位由系統(tǒng)清零,從靜默模式中喚醒,同時置位UART_ISR的RXB8_INTF和RX_INTF位;若地址不匹配,則只有UART_ISR的RXB8_INTF被置位,UART進(jìn)入靜默模式。
在庫函數(shù)中還有兩個在發(fā)送時會用到的函數(shù):
void UART_Set9bitAutomaticToggle(UART_TypeDef*UARTx, FunctionalState NewState);
//B8TOG設(shè)置,在地址幀發(fā)送結(jié)束后,B8TXD自動翻轉(zhuǎn)翻轉(zhuǎn),進(jìn)入數(shù)據(jù)幀格式
voidUART_Set9bitLevel(UART_TypeDef* UARTx, FunctionalState NewState);
//B8TXD設(shè)置,用于設(shè)置下一幀是地址幀還是數(shù)據(jù)幀
在主機(jī)與從機(jī)簡單配置之后,我們用簡單的數(shù)據(jù)測試配置的功能:
主機(jī)程序:
void UART1_9B_TX(u8addr,u8*str,u16 len)
{
UART_Set9bitLevel(UART1,ENABLE); //下一個字節(jié)為地址字節(jié)
UartSendByte(addr); //地址
UartSendGroup(str,len); //自動翻轉(zhuǎn)為數(shù)據(jù)字節(jié),發(fā)送str
}
intmain(void)
{
InitSystick();//systick初始化,方便調(diào)試
Uart_ConfigInit(9600);
UART1_9B_TX(0x52,"123",3); //向地址0x52發(fā)送0x31 0x32 0x33
UART1_9B_TX(0x5A,"456",3); //向地址0x5A發(fā)送0x34 0x35 0x36
UART1_9B_TX(0x53,"789",3); //向地址0x53發(fā)送0x37 0x38 0x39
while(1){ }
}
從機(jī)程序:
intmain(void)
{
InitSystick();//systick初始化,方便調(diào)試
Uart_ConfigInit(9600);
while(1){ } //等待接收數(shù)據(jù)
}
voidUART1_IRQHandler(void) //中斷處理函數(shù)
{
if(UART_GetITStatus(UART1, UART_IT_RXB8) )
{
UART_ClearITPendingBit(UART1, UART_IT_RXB8); //清除中斷標(biāo)志位
UART_ClearITPendingBit(UART1, UART_IT_RXIEN); //清除中斷標(biāo)志位,不接受地址字節(jié)數(shù)據(jù)
}
if(UART_GetITStatus(UART1, UART_IT_RXIEN) )
{
UART_ClearITPendingBit( UART1, UART_IT_RXIEN); //清除中斷標(biāo)志位
uartTXbuf[uartTXlen ++ ] = UART_ReceiveData(UART1);//接收數(shù)據(jù)
UartSendByte(UART_ReceiveData(UART1));
}
}
主機(jī)發(fā)送的數(shù)據(jù):0x152(地址) 0x031 0x0320x033 0x15A(地址) 0x0340x035 0x036 0x153(地址) 0x0370x038 0x039
從機(jī)將接收到的數(shù)據(jù)幀經(jīng)UART再進(jìn)行轉(zhuǎn)發(fā)。
圖3 測試結(jié)果
可以看到,從機(jī)在收到地址幀后,從機(jī)只在接收到0x15A之后從靜默模式切換回正常模式,接下來的數(shù)據(jù)會接收并觸發(fā)接收中斷,將接收到的0x34 0x350x36再發(fā)回主機(jī),在接收到0x152和0x153這兩個不匹配的地址后保持或切換到靜默模式,不再接收數(shù)據(jù)。
編輯:admin 最后修改時間:2023-03-22