CH432INT#中断问题

目前使用STM32+CH432,可以收发,但在设置INT#中断为外部输入中断后,即使两个串口有信息回复,也无法触发INT#中断,如果把void CH432Interrupt(void) 函数放在进程中轮询,INT#中断才会触发,但是正常流程应该是把CH432Interrupt(void)函数放在INT#中断服务函数里执行,请问可能是什么原因?

配置如下:

   UINT16 div;
    UINT8 DLL, DLM;
/**************************************************************************
          设置CH432串口0的寄存器
**************************************************************************/
    div = ( Fpclk >> 4 ) / CH432_BPS0;
    DLM = div >> 8;
    DLL = div & 0xff;
    WriteCH432Data( CH432_IER_PORT, BIT_IER_RESET);  //端口复位//
    WriteCH432Data( CH432_LCR_PORT, BIT_LCR_DLAB );    /* 设置DLAB为1 */
    WriteCH432Data( CH432_DLL_PORT, DLL );    /* 设置波特率 */
    WriteCH432Data( CH432_DLM_PORT, DLM );
    WriteCH432Data( CH432_FCR_PORT, BIT_FCR_FIFOEN );    /* 设置FIFO模式,触发点为14 */
    WriteCH432Data( CH432_LCR_PORT, BIT_LCR_WORDSZ1 | BIT_LCR_WORDSZ0 );    /* 字长8位,1位停止位、无校验 */
    WriteCH432Data( CH432_IER_PORT, BIT_IER_IEMODEM | BIT_IER_IELINES | BIT_IER_IETHRE | BIT_IER_IERECV );    /* 使能中断 */
    WriteCH432Data( CH432_MCR_PORT, BIT_MCR_OUT2);    /* 允许中断输出,DTR,RTS为1 */
/**************************************************************************
          设置CH432串口1的寄存器
**************************************************************************/
    div = ( Fpclk >> 4 ) / CH432_BPS1;
    DLM = div >> 8;
    DLL = div & 0xff;
    WriteCH432Data( CH432_IER1_PORT, BIT_IER_RESET);  //端口复位//
    WriteCH432Data( CH432_LCR1_PORT, BIT_LCR_DLAB );    /* 设置DLAB为1 */
    WriteCH432Data( CH432_DLL1_PORT, DLL );    /* 设置波特率 */
    WriteCH432Data( CH432_DLM1_PORT, DLM );
    WriteCH432Data( CH432_FCR1_PORT, BIT_FCR_FIFOEN );    /* 设置FIFO模式,触发点为14 */
    WriteCH432Data( CH432_LCR1_PORT, BIT_LCR_WORDSZ1 | BIT_LCR_WORDSZ0 );    /* 字长8位,1位停止位、无校验 */
    WriteCH432Data( CH432_IER1_PORT, BIT_IER_IEMODEM | BIT_IER_IELINES | BIT_IER_IETHRE | BIT_IER_IERECV );    /* 使能中断 */
    WriteCH432Data( CH432_MCR1_PORT, BIT_MCR_OUT2);    /* 允许中断输出,DTR,RTS为1 */


您好,这个初始化没有什么问题。

可以在接收数据时,查看CH432的INT#引脚是否会输出低电平,若有输出低电平,则可能是单片机没有抓到中断,可以检查一下单片机中断配置是否正确,CH432的中断是低电平有效,所以GPIO应该设置为上拉输入,中断是下降沿触发。


您好,INT#管脚需要外部加上拉电阻吗


如果正确设置IO的话,是不需要外接上拉电阻的


你好,最近没处理这个问题,目前测试,单片机外部中断输入脉冲是可以触发的,432芯片的INT#管脚没有输出下降沿,一直是低电平


IER:00 

IIR1:01 

IIR:01 

FCR:01 

MCR:00 

LSR:60 

MSR:00



您好,低电平应该是有中断产生才对。CH432在产生中断后根据不同的中断类型,需要读取相应的寄存器才会清除中断,如果一直是低电平,则说明中断没有清除,可以检查一下中断服务函数是否有清除中断。

下面的代码是对引脚PB10的设置,以及中断服务函数,其他代码部分可以参考CH432EVT提供的例程

void INT_Init(void)      //***初始化INT#**//
{
	GPIO_InitTypeDef GPIO_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	
	
	//-------------------------------------------
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;   //上拉输入	
	GPIO_Init(GPIOB, &GPIO_InitStructure);	
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource10);  
    /* Configure Button EXTI line */
    EXTI_InitStructure.EXTI_Line = EXTI_Line10;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;  
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

	/* Enable the EXTI Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	//--------------------------------------
}
void EXTI15_10_IRQHandler(void)
{
	EXTI_ClearITPendingBit(EXTI_Line10); //清空中断标志位,防止持续进入中断  	
    UartDetectInterrupt( );
}
UINT8 UartDetectInterrupt( )    /* 查询CH432的中断状态 */
{
    UINT8 InterruptStatus;
    UINT8 RcvNum = 0;
    UINT8 s,i;
    UINT8 ModemStatus;
    while( 1 )
    {
        InterruptStatus = ReadCH432Data( CH432_IIR_PORT )& ( ~ CH432_IIR_FIFOS_ENABLED );
        if( ( InterruptStatus & 0x01 ) )    /* 没有中断转到串口1 */
        {
            InterruptStatus = ReadCH432Data( CH432_IIR1_PORT) & ( ~ CH432_IIR_FIFOS_ENABLED );    /* 读串口1的中断状态 */
            if( ( InterruptStatus & 0x01 ) ) break;    /* 没有中断退出 */
            else
            {
                switch( InterruptStatus )
                {
                    case INT_NOINT:    /* 没有中断 */
                        break;
                    case INT_THR_EMPTY:    /* 发送保持寄存器空中断 */
                        break;
                    case INT_RCV_SUCCESS:    /* 串口接收可用数据中断 */
                        RcvNum = CH432Seril1Rcv( buf );
					    buf[RcvNum]=0;
					    printf("%s", buf );
//					    CH432Seril0Send( buf, RcvNum );
                        break;
                    case INT_RCV_LINES:    /* 接收线路状态中断 */
                         ReadCH432Data( CH432_LSR1_PORT);
                        break;
                    case INT_RCV_OVERTIME:    /* 接收数据超时中断 */
                        RcvNum = CH432Seril1Rcv( buf );
					    buf[RcvNum]=0;
					    printf("%s", buf );
//                        CH432Seril1Send( buf, RcvNum );
                        break;
                    default:    /* 不可能发生的中断 */
                        break;
                }
            }
        } 
        else
        {
            switch( InterruptStatus )
            {
                case INT_NOINT:    /* 没有中断 */
                    break;
                case INT_THR_EMPTY:    /* 发送保持寄存器空中断 */
                    break;
                case INT_RCV_SUCCESS:    /* 串口接收可用数据中断 */
                    RcvNum = CH432Seril0Rcv( buf );
					buf[RcvNum]=0;
					printf("%s", buf );
//                    UART0_SendByte( RcvNum );
//                    CH432Seril0Send( buf, RcvNum );
                    break;
                case INT_RCV_LINES :    /* 接收线路状态中断 */
                    ReadCH432Data( CH432_LSR_PORT);
                    break;
                case INT_RCV_OVERTIME:    /* 接收数据超时中断 */
                    RcvNum = CH432Seril0Rcv( buf );
					buf[RcvNum]=0;
					printf("%s", buf );
//                    UART0_SendByte( RcvNum );
//                    CH432Seril0Send( buf, RcvNum );
                    break;
                default:    /* 不可能发生的中断 */
                    break;
            }
        }
    }
    return( InterruptStatus );
}




目前发现下面的配置通讯是比较稳定的,BIT_IER_IETHRE 中断必须屏蔽,否则无法接收,请问是什么原因
void InitCH432( void )    /* 初始化CH432 */
{
    UINT16 div;
    UINT8 DLL, DLM;
/**************************************************************************
          设置CH432串口0的寄存器

**************************************************************************/
    div = ( Fpclk >> 4 ) / CH432_BPS0;
    DLM = div >> 8;
    DLL = div & 0xff;
    WriteCH432Data( CH432_IER_PORT, BIT_IER_RESET);  //端口复位//
    WriteCH432Data( CH432_LCR_PORT, BIT_LCR_DLAB );    /* 设置DLAB为1 */
    WriteCH432Data( CH432_DLL_PORT, DLL );    /* 设置波特率 */
    WriteCH432Data( CH432_DLM_PORT, DLM );
    WriteCH432Data( CH432_FCR_PORT, BIT_FCR_RECVTG1 | BIT_FCR_RECVTG0 | BIT_FCR_FIFOEN );    /* 设置FIFO模式,触发点为14 */
    WriteCH432Data( CH432_LCR_PORT, BIT_LCR_WORDSZ1 | BIT_LCR_WORDSZ0 );    /* 字长8位,1位停止位、无校验 */
    WriteCH432Data( CH432_IER_PORT, BIT_IER_IEMODEM | BIT_IER_IELINES | /*BIT_IER_IETHRE |*/ BIT_IER_IERECV);    /* 使能中断 */
    WriteCH432Data( CH432_MCR_PORT, BIT_MCR_OUT2);    /* 允许中断输出,DTR,RTS为1 */

/**************************************************************************
          设置CH432串口1的寄存器

**************************************************************************/
    div = ( Fpclk >> 4 ) / CH432_BPS1;
    DLM = div >> 8;
    DLL = div & 0xff;
    WriteCH432Data( CH432_IER1_PORT, BIT_IER_RESET);  //端口复位//
    WriteCH432Data( CH432_LCR1_PORT, BIT_LCR_DLAB );    /* 设置DLAB为1 */
    WriteCH432Data( CH432_DLL1_PORT, DLL );    /* 设置波特率 */
    WriteCH432Data( CH432_DLM1_PORT, DLM );
    WriteCH432Data( CH432_FCR1_PORT, BIT_FCR_RECVTG1 | BIT_FCR_RECVTG0 | BIT_FCR_FIFOEN );    /* 设置FIFO模式,触发点为14 */
    WriteCH432Data( CH432_LCR1_PORT, BIT_LCR_WORDSZ1 | BIT_LCR_WORDSZ0 );    /* 字长8位,1位停止位、无校验 */
    WriteCH432Data( CH432_IER1_PORT, BIT_IER_IEMODEM | BIT_IER_IELINES | /*BIT_IER_IETHRE |*/ BIT_IER_IERECV);    /* 使能中断 */
    WriteCH432Data( CH432_MCR1_PORT, BIT_MCR_OUT2);    /* 允许中断输出,DTR,RTS为1 */

}



您好:

THR中断是“发送保持寄存器空”中断,当您的THR寄存器空时会产生该中断。如果当您开启这个中断却导致无法接收数据,您可以检查INT引脚是否为低电平,若INT引脚为低电平则说明有中断没有清除,可以查询IIR 寄存器以判断相应中断并清除中断。


目前来看,开启的状态下,则无法产生中断,屏蔽状态下,就可以产生中断,测试久了也不稳定,中断函数如下:

UINT8 CH432Interrupt(void)  /* 中断方式处理 */
{
    UINT8 InterruptStatus;
    UINT8 RcvNum = 0, i;
    while(1)
    {
        InterruptStatus = ReadCH432Data( CH432_IIR_PORT ) & ( ~ CH432_IIR_FIFOS_ENABLED );
        if( ( InterruptStatus & 0x01 ) )    /* 没有中断转到串口1 */
        {}
        else
        {
        	switch( InterruptStatus )
            {
                case INT_NOINT:    /* 没有中断 */
                        break;
                case INT_THR_EMPTY:    /* 发送保持寄存器空中断 */
                		printf("INT_THR_EMPTY\r\n");
                        break;
                case INT_RCV_SUCCESS:    /* 串口接收可用数据中断 */
                        RcvNum = CH432Seril0Rcv( uart_dma_rx_buf3 );
                        break;
                case INT_RCV_LINES:    /* 接收线路状态中断 */
                        ReadCH432Data( CH432_LSR_PORT);
                        break;
                case INT_RCV_OVERTIME:    /* 接收数据超时中断 */
                        RcvNum = CH432Seril0Rcv( uart_dma_rx_buf3 );
                        break;
                default:    /* 不可能发生的中断 */
                        break;
            }
        }

        InterruptStatus = ReadCH432Data( CH432_IIR1_PORT ) & ( ~ CH432_IIR_FIFOS_ENABLED );    /* 读串口1的中断状态 */
        if( ( InterruptStatus & 0x01 ) )   break;  /* 没有中断退出 */
        else
        {
            switch( InterruptStatus )
            {
                case INT_NOINT:    /* 没有中断 */
                    break;
                case INT_THR_EMPTY:    /* 发送保持寄存器空中断 */
                	printf("INT_THR1_EMPTY\r\n");
                    break;
                case INT_RCV_SUCCESS:    /* 串口接收可用数据中断 */
                    RcvNum = CH432Seril1Rcv(uart_dma_rx_buf4);
                    break;
                case INT_RCV_LINES:    /* 接收线路状态中断 */
                    ReadCH432Data( CH432_LSR1_PORT);
                    break;
                case INT_RCV_OVERTIME:    /* 接收数据超时中断 */
                    RcvNum = CH432Seril1Rcv(uart_dma_rx_buf4);
                    break;
                default:    /* 不可能发生的中断 */
                    break;
            }
        }
    }
    return( InterruptStatus );
}



屏蔽BIT_IER_IETHRE中断,是否会导致接收不稳定的情况


您好:

屏蔽BIT_IER_IETHRE中断是可以正常收发数据的,发送数据是由您主动发起,可以不用开启发送寄存器空中断,不会造成不稳定的情况


我现在的情况,就是只有屏蔽BIT_IER_IETHRE才能正常接收数据,不屏蔽就产生了一次INT_THR_EMPTY中断,就无法再进入中断了,请问这可能是什么原因导致的


您好:

在初始化结束后,您可以先检查一下各个寄存器写入的值是否正确,如果配置的值和预想的值不一样的话,可能是以下原因。

IETHR由0到1时会产生一个INT_THR_EMPTY中断。在初始化时,您先是写了一个“IETHR由0到1”从而产生了一个INT_THR_EMPTY中断,而在后续的打开MCR寄存器的OUT2位时,相当于允许了串口的中断输出,使INT#引脚拉低,进入中断服务函数,在这个过程中,可能导致您的某些寄存器的配置出现错误。

解决方法有:

1.SPI的接口函数要按照以下格式(推荐该方法)。

接口函数()

{

   SCS拉高    //避免某些情况(如中断)导致的SCS状态不正常,从而影响到后续的数据写入

   SCS拉低

   输入数据

   SCS拉高

}

2.在初始化CH432后,再开启中断,并在开启中断后读CH432的中断类型清中断。



#define CH432_BPS0 230400    /* 定义CH432串口0通讯波特率 */
#define CH432_BPS1 230400    /* 定义CH432串口1通讯波特率 */
#define Fpclk      (1843200) //1843200    /* 定义内部时钟频率    */
如何设置CH432的波特率未230400,外部晶振22.1184MHz



您好

波特率的设置公式是:所需通讯波特率 = 串口内部基准时钟 / 16 / DLL和DLM寄存器值

其中串口内部基准时钟由晶振以及内部倍频决定。由下表可知,当使用22.1184MHz晶振,内部2倍频时,最大波特率为2.7648Mbps。

image.png


即,所需配置为

  1. 先配置CK2X位为1,使用内部2倍频,此时的内部基准时钟为44.2368MHz。

  2. 根据公式代入所需230400的波特率,可以得出DLL和DLM寄存器的值为12,所以配置DLL的值为0x0C,DLM的值为0x00。


只有登录才能回复,可以选择微信账号登录