MM32SPIN2x 电机专用MCU功能特色——UART模块Bit9功能
上一章节中已经教大家如何使用MM32SPIN2x的比较器轮询功能,本章节将与大家一起配置UART的Bit9模式实现多机通讯功能。
图1UART多机通信
在双机通讯中,UART的8bit通信的第九位一般是奇偶校验位,而多机通讯中,第九位用于标识地址或数据,常用1表示后面的是从机地址,0表示后面的是数据。我们通常希望只有被寻址的接收者才被激活,来接收随后的数据,这样就可以减少由未被寻址的接收器的参与带来的多余的UART服务开销。未被寻址的设备可启用其静默功能置于静默模式。在静默模式里,任何接收状态位都不会被设置,所有接收中断被禁止。
图2UART多机通信
通过 UART 可以实现多处理器通信 (将几个 UART 连在一个网络里)。例如某个 UART 设备可以是主,它的 TX 输出和其他 UART 从设备的 RX 输入相连接; UART 从设备各自的TX 输出逻辑地与在一起,并且和主设备的 RX 输入相连接。
在多处理器配置中,我们通常希望只有被寻址的接收者才被激活,来接收随后的数据,这样就可以减少由未被寻址的接收器的参与带来的多余的 UART 服务开销。
未被寻址的设备可启用其静默功能置于静默模式。在静默模式里:
? 任何接收状态位都不会被设置。
? 所有接收中断被禁止。
? UART_CCR 寄存器中的 RWU 位被置 1。 RWU 可以被硬件自动控制或在某个条件下由软件写入。
根据 UART_CCR 寄存器中的 WAKE 位状态, UART 可以用二种方法进入或退出静默模式。
? 如果 WAKE 位被复位:进行空闲总线检测。
? 如果 WAKE 位被设置:进行地址标记检测。
今天与大家一起学习如何配置使用MM32SPIN2x的UART的Bit9模式实现多机通讯功能。
在使能UART_CCR寄存器的B8EN控制位后,UART就会使能9位数据的发送和接收,可以发送和接收9位数据。注意:在 B8EN 使能后,奇偶校验使能位PEN不起作用。
数据发送的时候,在写入数据到发送寄存器UART_TDR前,需要先设置B8TXD。B8TXD作为发送数据的MSB和UART_TDR的值同时发送。如果设置了B8TOG,如果B8TXD与B8POL相同时,表示该数据作为地址帧或者同步帧,发送结束后B8TXD会自动翻转。在接下来的数据发送过程中,不需要再设置B8TXD为无效电平。
数据接收的时候,接收数据的最高位可以从寄存器位B8RXD读到。如果接收的B8RXD与B8POL相同时,中断状态寄存器UART_ISR的RXB8_INTF位会置位。
UART9Bit模式的配置步骤如下:
1) 串口时钟使能,GPIO时钟使能
2) 串口复位
3) GPIO端口模式设置
4) 串口参数初始化
5)9Bit参数配置
5) 开启中断并且初始化NVIC(可选)
6) 使能串口
7) 编写中断处理函数
程序中配置如下:
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);
//串口复位及参数初始化
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参数配置
UART_Enable9bit(UART1,ENABLE);//UART9bit使能控制位
UART_Set9bitPolarity(UART1,UART_9bit_Polarity_High); //第九位高电平有效
UART_WakeUpConfig(UART1,UART_WakeUp_AddressMark);//地址标记唤醒
UART_ReceiverWakeUpCmd(UART1,ENABLE);//静默模式启用,从机配置静默模式,如果作为主机,需要将该句disable
UART_SetRXMASK(UART1,0xFF);//启用8位地址匹配
UART_SetRXAddress(UART1,0x5A);//地址设置为0x5A
UART_ITConfig(UART1, UART_IT_RXB8, ENABLE ); //开启地址帧帧中断
//使能串口
UART_Cmd(UART1,ENABLE);
}
在上述配置中,我们启用了地址标记唤醒,在接收到的地址帧中的地址与UART_RXADDR中的地址匹配时,UART_CCR中的RWU位由系统清零,从静默模式中唤醒,同时置位UART_ISR的RXB8_INTF和RX_INTF位;若地址不匹配,则只有UART_ISR的RXB8_INTF被置位,UART进入静默模式。
在库函数中还有两个在发送时会用到的函数:
void UART_Set9bitAutomaticToggle(UART_TypeDef*UARTx, FunctionalState NewState);
//B8TOG设置,在地址帧发送结束后,B8TXD自动翻转翻转,进入数据帧格式
voidUART_Set9bitLevel(UART_TypeDef* UARTx, FunctionalState NewState);
//B8TXD设置,用于设置下一帧是地址帧还是数据帧
在主机与从机简单配置之后,我们用简单的数据测试配置的功能:
主机程序:
void UART1_9B_TX(u8addr,u8*str,u16 len)
{
UART_Set9bitLevel(UART1,ENABLE); //下一个字节为地址字节
UartSendByte(addr); //地址
UartSendGroup(str,len); //自动翻转为数据字节,发送str
}
intmain(void)
{
InitSystick();//systick初始化,方便调试
Uart_ConfigInit(9600);
UART1_9B_TX(0x52,"123",3); //向地址0x52发送0x31 0x32 0x33
UART1_9B_TX(0x5A,"456",3); //向地址0x5A发送0x34 0x35 0x36
UART1_9B_TX(0x53,"789",3); //向地址0x53发送0x37 0x38 0x39
while(1){ }
}
从机程序:
intmain(void)
{
InitSystick();//systick初始化,方便调试
Uart_ConfigInit(9600);
while(1){ } //等待接收数据
}
voidUART1_IRQHandler(void) //中断处理函数
{
if(UART_GetITStatus(UART1, UART_IT_RXB8) )
{
UART_ClearITPendingBit(UART1, UART_IT_RXB8); //清除中断标志位
UART_ClearITPendingBit(UART1, UART_IT_RXIEN); //清除中断标志位,不接受地址字节数据
}
if(UART_GetITStatus(UART1, UART_IT_RXIEN) )
{
UART_ClearITPendingBit( UART1, UART_IT_RXIEN); //清除中断标志位
uartTXbuf[uartTXlen ++ ] = UART_ReceiveData(UART1);//接收数据
UartSendByte(UART_ReceiveData(UART1));
}
}
主机发送的数据:0x152(地址) 0x031 0x0320x033 0x15A(地址) 0x0340x035 0x036 0x153(地址) 0x0370x038 0x039
从机将接收到的数据帧经UART再进行转发。
图3 测试结果
可以看到,从机在收到地址帧后,从机只在接收到0x15A之后从静默模式切换回正常模式,接下来的数据会接收并触发接收中断,将接收到的0x34 0x350x36再发回主机,在接收到0x152和0x153这两个不匹配的地址后保持或切换到静默模式,不再接收数据。
编辑:admin 最后修改时间:2023-03-22