kdusrasf 发表于 前天 10:05

串口1 用定时器1不工作BUG

大家好,请教一下有关串口1用定时器1作波特率时无法工作(暂未找到原因)


串口及定时器相关函数如下:

这是串口1初始化函数

void XC1_init(u16 BaudRate)
{

        COMx_InitDefine                COMx_InitStructure;                                       
        COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;       
        COMx_InitStructure.UART_BRT_Use   = BRT_Timer1;        (此处改BRT_Timer2时可以正常工作)               
        COMx_InitStructure.UART_BaudRate= BaudRate;                       
        COMx_InitStructure.UART_RxEnable= ENABLE;                               
        COMx_InitStructure.BaudRateDouble = DISABLE;                       
        COMx_InitStructure.UART_Interrupt = ENABLE;                               
        COMx_InitStructure.UART_Polity    = Polity_1;                       
        COMx_InitStructure.UART_P_SW      = UART1_SW_P30_P31;       
        UART_Configuration(UART1, &COMx_InitStructure);       
       
}


这是串口2初始化函数:


void XC2_init(u16 BaudRate)
{

        COMx_InitDefine                COMx_InitStructure;                                       
        COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;       
        COMx_InitStructure.UART_BRT_Use   = BRT_Timer2;                       
        COMx_InitStructure.UART_BaudRate= BaudRate;                       
        COMx_InitStructure.UART_RxEnable= ENABLE;                               
        COMx_InitStructure.BaudRateDouble = DISABLE;                       
        COMx_InitStructure.UART_Interrupt = ENABLE;                               
        COMx_InitStructure.UART_Polity    = Polity_1;                       
        COMx_InitStructure.UART_P_SW      = UART2_SW_P10_P11;       
        UART_Configuration(UART2, &COMx_InitStructure);       
       
}




这是UART_Configuration串口初始化程序(用库、未改)

u8 UART_Configuration(u8 UARTx, COMx_InitDefine *COMx)
{
        u8        i;
        u32        j;
       
#ifdef UART1
        if(UARTx == UART1)
        {
                COM1.id = 1;
                COM1.TX_read    = 0;
                COM1.TX_write   = 0;
                COM1.B_TX_busy= 0;
                COM1.RX_Cnt   = 0;
                COM1.RX_TimeOut = 0;
                COM1.B_RX_OK    = 0;
                for(i=0; i<COM_TX1_Lenth; i++)        TX1_Buffer = 0;
                for(i=0; i<COM_RX1_Lenth; i++)        RX1_Buffer = 0;

                if(COMx->UART_Polity > Polity_3)        return 2;        //错误
                UART1_Polity(COMx->UART_Polity);        //指定中断优先级(低到高) Polity_0,Polity_1,Polity_2,Polity_3
                if(COMx->UART_Mode > UART_9bit_BRTx)        return 2;        //模式错误
                SCON = (SCON & 0x3f) | COMx->UART_Mode;
                if((COMx->UART_Mode == UART_9bit_BRTx) || (COMx->UART_Mode == UART_8bit_BRTx))        //可变波特率
                {
                        j = (MAIN_Fosc / 4) / COMx->UART_BaudRate;        //按1T计算
                        if(j >= 65536UL)        return 2;        //错误
                        j = 65536UL - j;
                        if(COMx->UART_BRT_Use == BRT_Timer1)
                        {
                                TR1 = 0;
                                AUXR &= ~0x01;                //S1 BRT Use Timer1;
                                TMOD &= ~(1<<6);        //Timer1 set As Timer
                                TMOD &= ~0x30;                //Timer1_16bitAutoReload;
                                AUXR |=(1<<6);        //Timer1 set as 1T mode
                                TH1 = (u8)(j>>8);
                                TL1 = (u8)j;
                                ET1 = 0;        //禁止中断
                                TMOD &= ~0x40;        //定时
                                INT_CLKO &= ~0x02;        //不输出时钟
                                TR1= 1;
                        }
                        else if(COMx->UART_BRT_Use == BRT_Timer2)
                        {
                                AUXR &= ~(1<<4);        //Timer stop
                                AUXR |= 0x01;                //S1 BRT Use Timer2;
                                AUXR &= ~(1<<3);        //Timer2 set As Timer
                                AUXR |=(1<<2);        //Timer2 set as 1T mode
                                TH2 = (u8)(j>>8);
                                TL2 = (u8)j;
                                IE2&= ~(1<<2);        //禁止中断
                                AUXR |=(1<<4);        //Timer run enable
                        }
                        else return 2;        //错误
                }
                else if(COMx->UART_Mode == UART_ShiftRight)
                {
                        if(COMx->BaudRateDouble == ENABLE)        AUXR |=(1<<5);        //固定波特率SysClk/2
                        else                                                                AUXR &= ~(1<<5);        //固定波特率SysClk/12
                }
                else if(COMx->UART_Mode == UART_9bit)        //固定波特率SysClk*2^SMOD/64
                {
                        if(COMx->BaudRateDouble == ENABLE)        PCON |=(1<<7);        //固定波特率SysClk/32
                        else                                                                PCON &= ~(1<<7);        //固定波特率SysClk/64
                }
                if(COMx->UART_Interrupt == ENABLE)        ES = 1;        //允许中断
                else                                                                ES = 0;        //禁止中断
                if(COMx->UART_RxEnable == ENABLE)        REN = 1;        //允许接收
                else                                                                REN = 0;        //禁止接收
                P_SW1 = (P_SW1 & 0x3f) | (COMx->UART_P_SW & 0xc0);        //切换IO
                return        0;
        }
#endif
#ifdef UART2
        if(UARTx == UART2)
        {
                COM2.id = 2;
                COM2.TX_read    = 0;
                COM2.TX_write   = 0;
                COM2.B_TX_busy= 0;
                COM2.RX_Cnt   = 0;
                COM2.RX_TimeOut = 0;
                COM2.B_RX_OK    = 0;
                for(i=0; i<COM_TX2_Lenth; i++)        TX2_Buffer = 0;
                for(i=0; i<COM_RX2_Lenth; i++)        RX2_Buffer = 0;

                if((COMx->UART_Mode == UART_9bit_BRTx) ||(COMx->UART_Mode == UART_8bit_BRTx))        //可变波特率
                {
                        if(COMx->UART_Polity > Polity_3)        return 2;        //错误
                        UART2_Polity(COMx->UART_Polity);        //指定中断优先级(低到高) Polity_0,Polity_1,Polity_2,Polity_3
                        if(COMx->UART_Mode == UART_9bit_BRTx)        S2CON |=(1<<7);        //9bit
                        else                                                                        S2CON &= ~(1<<7);        //8bit
                        j = (MAIN_Fosc / 4) / COMx->UART_BaudRate;        //按1T计算
                        if(j >= 65536UL)        return 2;        //错误
                        j = 65536UL - j;
                        AUXR &= ~(1<<4);        //Timer stop
                        AUXR &= ~(1<<3);        //Timer2 set As Timer
                        AUXR |=(1<<2);        //Timer2 set as 1T mode
                        TH2 = (u8)(j>>8);
                        TL2 = (u8)j;
                        IE2&= ~(1<<2);        //禁止中断
                        AUXR |=(1<<4);        //Timer run enable
                }
                else        return 2;        //模式错误
                if(COMx->UART_Interrupt == ENABLE)        IE2   |=1;                //允许中断
                else                                                                IE2   &= ~1;                //禁止中断
                if(COMx->UART_RxEnable == ENABLE)        S2CON |=(1<<4);        //允许接收
                else                                                                S2CON &= ~(1<<4);        //禁止接收
                P_SW2 = (P_SW2 & ~1) | (COMx->UART_P_SW & 0x01);        //切换IO
                return        0;
        }
#endif
#ifdef UART3
        if(UARTx == UART3)
        {
                COM3.id = 3;
                COM3.TX_read    = 0;
                COM3.TX_write   = 0;
                COM3.B_TX_busy= 0;
                COM3.RX_Cnt   = 0;
                COM3.RX_TimeOut = 0;
                COM3.B_RX_OK    = 0;
                for(i=0; i<COM_TX3_Lenth; i++)        TX3_Buffer = 0;
                for(i=0; i<COM_RX3_Lenth; i++)        RX3_Buffer = 0;

                if((COMx->UART_Mode == UART_9bit_BRTx) || (COMx->UART_Mode == UART_8bit_BRTx))        //可变波特率
                {
                        if(COMx->UART_Polity > Polity_3)        return 2;        //错误
                        UART3_Polity(COMx->UART_Polity);        //指定中断优先级(低到高) Polity_0,Polity_1,Polity_2,Polity_3
                        if(COMx->UART_Mode == UART_9bit_BRTx)        S3_9bit();        //9bit
                        else                                                                        S3_8bit();        //8bit
                        j = (MAIN_Fosc / 4) / COMx->UART_BaudRate;        //按1T计算
                        if(j >= 65536UL)        return 2;        //错误
                        j = 65536UL - j;
                        if(COMx->UART_BRT_Use == BRT_Timer3)
                        {
                                S3_BRT_UseTimer3();                //S3 BRT Use Timer3;
                                TH3 = (u8)(j>>8);
                                TL3 = (u8)j;
                                T4T3M = 0x0a;                        //Timer3 set As Timer, 1T mode, Start timer3
                        }
                        else if(COMx->UART_BRT_Use == BRT_Timer2)
                        {
                                AUXR &= ~(1<<4);                //Timer stop
                                S3_BRT_UseTimer2();        //S3 BRT Use Timer2;
                                AUXR &= ~(1<<3);                //Timer2 set As Timer
                                AUXR |=(1<<2);                //Timer2 set as 1T mode
                                TH2 = (u8)(j>>8);
                                TL2 = (u8)j;
                                IE2&= ~(1<<2);        //禁止中断
                                AUXR |=(1<<4);        //Timer run enable
                        }
                        else return 2;        //错误
                }
                else        return 2;        //模式错误
                if(COMx->UART_Interrupt == ENABLE)        S3_Int_Enable();                //允许中断
                else                                                                S3_Int_Disable();                //禁止中断
                if(COMx->UART_RxEnable == ENABLE)        S3_RX_Enable();        //允许接收
                else                                                                S3_RX_Disable();        //禁止接收
                P_SW2 = (P_SW2 & ~2) | (COMx->UART_P_SW & 0x02);        //切换IO
                return        0;
        }
#endif
#ifdef UART4
        if(UARTx == UART4)
        {
                COM4.id = 3;
                COM4.TX_read    = 0;
                COM4.TX_write   = 0;
                COM4.B_TX_busy= 0;
                COM4.RX_Cnt   = 0;
                COM4.RX_TimeOut = 0;
                COM4.B_RX_OK    = 0;
                for(i=0; i<COM_TX4_Lenth; i++)        TX4_Buffer = 0;
                for(i=0; i<COM_RX4_Lenth; i++)        RX4_Buffer = 0;

                if((COMx->UART_Mode == UART_9bit_BRTx) || (COMx->UART_Mode == UART_8bit_BRTx))        //可变波特率
                {
                        if(COMx->UART_Polity > Polity_3)        return 2;        //错误
                        UART4_Polity(COMx->UART_Polity);        //指定中断优先级(低到高) Polity_0,Polity_1,Polity_2,Polity_3
                        if(COMx->UART_Mode == UART_9bit_BRTx)        S4_9bit();        //9bit
                        else                                                                        S4_8bit();        //8bit
                        j = (MAIN_Fosc / 4) / COMx->UART_BaudRate;        //按1T计算
                        if(j >= 65536UL)        return 2;        //错误
                        j = 65536UL - j;
                        if(COMx->UART_BRT_Use == BRT_Timer4)
                        {
                                S4_BRT_UseTimer4();                //S4 BRT Use Timer4;
                                TH4 = (u8)(j>>8);
                                TL4 = (u8)j;
                                T4T3M = 0xa0;                        //Timer4 set As Timer, 1T mode, Start timer4
                        }
                        else if(COMx->UART_BRT_Use == BRT_Timer2)
                        {
                                AUXR &= ~(1<<4);                //Timer stop
                                S4_BRT_UseTimer2();        //S4 BRT Use Timer2;
                                AUXR &= ~(1<<3);                //Timer2 set As Timer
                                AUXR |=(1<<2);                //Timer2 set as 1T mode
                                TH2 = (u8)(j>>8);
                                TL2 = (u8)j;
                                IE2&= ~(1<<2);        //禁止中断
                                AUXR |=(1<<4);        //Timer run enable
                        }
                        else return 2;        //错误
                }
                else        return 2;        //模式错误
                if(COMx->UART_Interrupt == ENABLE)        S4_Int_Enable();                //允许中断
                else                                                                S4_Int_Disable();                //禁止中断
                if(COMx->UART_RxEnable == ENABLE)        S4_RX_Enable();        //允许接收
                else                                                                S4_RX_Disable();        //禁止接收
                P_SW2 = (P_SW2 & ~4) | (COMx->UART_P_SW & 0x04);        //切换IO
                return        0;
        }
#endif
        return        2;        //错误
}



这是定时器0初始化:

void Systick_Init(void)reentrant
{   
        unsigned int temp;
       
        AUXR &= 0x7F;                //定时器时钟12T模式
        TMOD &= 0xF0;                //设置定时器模式自动重装载

//根据OS_TICKS_PER_SEC设置值来确认定时器初始值       
        temp = 65536 - MAIN_Fosc/OS_TICKS_PER_SEC/12;
       
        TL0 = temp%256 ;               
        TH0 = temp/256 ;               
        TF0 = 0;                //清除TF0标志
        TR0 = 1;                //定时器0开始计时
        ET0 = 1;    //使能定时器中断
}




另外还用到定时器4

void IR_init(void)//红外初始化:20键
{       
       

        INTCLKO |= 0X10;//使能 INT2 下降沿中断
        P3SR = 0;
       
       
        T4T3M &= 0xDF;                        //定时器时钟12T模式
        T4L = 0;                                //设置定时初始值
        T4H = 0;                                //设置定时初始值
       
        T4T3M &= 0x7f;                        //定时器4停止计时       

       
        EA = 1;
}       



问题描述:当串口1串口2共用定时器2作波特率时,都能正常工作;当串口1用定时器1串口2用
                定时器2作波特率时串口1不工作,串口2、定时器0、定时器4能正常工作。

谢谢。




国芯人工智能 发表于 前天 10:08

大家好,关于您提到的“串口1使用定时器1作为波特率发生器时无法工作”的问题,以下为专业分析及建议:

首先,从代码结构来看,串口1的初始化函数 XC1init 中设置了 UARTBRTUse = BRTTimer1,而当改为 BRTTimer2 时可以正常工作。这表明问题可能与定时器1的配置或资源冲突有关。

一、可能原因分析

1. 定时器1未正确初始化
   若定时器1未按照波特率计算方式进行配置(如计数模式、预分频值、自动重载值等),可能导致其输出频率不符合串口所需的波特率要求,从而导致通信失败。

2. 定时器1与其他外设冲突
   检查是否在其他地方对定时器1进行了配置或占用(如PWM、ADC触发等),若存在资源冲突,可能导致定时器1无法正常工作。

3. 引脚复用配置错误
   串口1使用的P30和P31引脚是否已正确配置为串口功能?若引脚未正确设置为UART模式,即使定时器1正常工作,串口也无法收发数据。

4. 中断优先级或使能问题
   串口1的中断是否被正确使能?同时检查中断服务函数是否被正确注册并执行。若中断未响应,也可能导致通信异常。

5. 波特率计算错误
   确保 BaudRate 值符合定时器1的计数范围,且计算方式正确。例如,若系统时钟为11.0592MHz,波特率为9600时,定时器1的初值应为 (230400 / 9600) - 1 = 23(假设使用8位模式)。

6. 硬件连接或电平问题
   检查串口1的TXD和RXD是否连接正确,是否存在短路或断路;同时确认外部设备的电平是否匹配(如TTL/RS232转换芯片)。

二、建议排查步骤

1. 检查定时器1的配置
   确认定时器1的模式(如方式0/1/2)、预分频值、自动重载值是否符合波特率计算要求,并确保其已启动。

2. 验证引脚配置
   使用调试工具或示波器检测P30和P31是否有信号输出,确认引脚是否被正确配置为UART功能。

3. 查看中断配置
   确保串口1的中断使能位已设置,并检查中断服务函数是否被正确调用。

4. 对比串口2配置
   由于串口2使用定时器2可正常工作,建议对比两者的配置差异,特别是定时器参数、引脚定义和中断设置。

5. 测试不同波特率
   尝试使用不同的波特率值,观察是否仍存在问题,以排除特定波特率下的配置错误。

6. 查阅数据手册
   参考芯片的数据手册,确认定时器1与串口1的兼容性,以及是否支持通过定时器1作为波特率源。

三、总结

串口1使用定时器1作为波特率发生器时无法工作,可能涉及定时器配置、引脚设置、中断控制或多任务资源冲突等多个方面。建议按上述步骤逐一排查,并结合调试工具进行验证。如问题仍未解决,可提供更详细的代码片段或硬件配置信息,以便进一步分析。

如有其他疑问,欢迎继续交流。

[本文内容由国芯人工智能辅助生成,仅供参考]

ercircle 发表于 前天 11:39

请问用的哪个型号?


STC15W408AS没有定时1,串口不能选定时器1作波特率发生器

kdusrasf 发表于 前天 11:39

ercircle 发表于 2025-9-1 11:39
请问用的哪个型号?



STC8H8K64UTSSOP20。能留个邮箱吗,我把资料发给您?

ercircle 发表于 前天 11:49

kdusrasf 发表于 2025-9-1 11:39
STC8H8K64UTSSOP20


可以用AiCube生成的
拿这个试下,串口1定时器1,串口2定时器2,8h8K64U测试正常:


DebugLab 发表于 前天 12:40

kdusrasf 发表于 2025-9-1 11:39
STC8H8K64UTSSOP20。能留个邮箱吗,我把资料发给您?

可直接上传程序文件,程序涉及商业机密(怕同行抄袭的)或无关部分可以删除,但要保证编译通过,尽量提供可复现问题的最简程序

DebugLab 发表于 前天 12:46

这是8G系列串口1使用定时器1做波特率发生器的程序,测试通过,8H系列也通用的

https://www.stcaimcu.com/thread-16321-1-1.html

神农鼎 发表于 前天 12:48


用这个测试程序来修改:





#include "stc8h.h"                                //包含STC8H的头文件

#include "intrins.h"                        //使用_nop_()函数所必须要包含的头文件,
                                                                //否则延时函数中调用的_nop_()函数没有被头文件引用过来,
                                                                //会导致编译器找不到这个而函数而报错。


unsigned char int0_flag = 0;        //定义1个位变量,INT0事件位变量标志,记录INT0已产生中断
// 供主循环查询INT0是否已产生中断,在主循环中处理INT0的中断事件任务,不堵塞其他中断
unsigned char int1_flag = 0;        //定义1个位变量,INT1事件位变量标志,记录INT1已产生中断
// 供主循环查询INT1是否已产生中断,在主循环中处理INT1的中断事件任务,不堵塞其他中断
unsigned char int2_flag = 0;        //定义1个位变量,INT2事件位变量标志,记录INT2已产生中断
// 供主循环查询INT2是否已产生中断,在主循环中处理INT2的中断事件任务,不堵塞其他中断
unsigned char int3_flag = 0;        //定义1个位变量,INT3事件位变量标志,记录INT3已产生中断
// 供主循环查询INT3是否已产生中断,在主循环中处理INT3的中断事件任务,不堵塞其他中断

unsigned char t0_flag = 0;                //定义1个位变量,T0事件位变量标志,记录定时器0已产生中断
// 供主循环查询定时器0是否已产生中断,在主循环中处理定时器0的中断事件任务,不堵塞其他中断
unsigned char t1_flag = 0;                //定义1个位变量,T1事件位变量标志,记录定时器1已产生中断
// 供主循环查询定时器1是否已产生中断,在主循环中处理定时器1的中断事件任务,不堵塞其他中断
unsigned char t3_flag = 0;                //定义1个位变量,T3事件位变量标志,记录定时器3已产生中断
// 供主循环查询定时器3是否已产生中断,在主循环中处理定时器3的中断事件任务,不堵塞其他中断
unsigned char t4_flag = 0;                //定义1个位变量,T4事件位变量标志,记录定时器4已产生中断
// 供主循环查询定时器4是否已产生中断,在主循环中处理定时器4的中断事件任务,不堵塞其他中断

unsigned char uart1_txflag = 0;        //定义1个位变量,UART1事件位变量标志,记录UART1已产生发送中断
// 供主循环查询UART1是否已产生发送中断,在主循环中处理UART1的中断事件任务,不堵塞其他中断
unsigned char uart1_rxflag = 0;        //定义1个位变量,UART1事件位变量标志,记录UART1已产生接收中断
// 供主循环查询UART1是否已产生接收中断,在主循环中处理UART1的中断事件任务,不堵塞其他中断
unsigned char uart2_txflag = 0;        //定义1个位变量,UART2事件位变量标志,记录UART2已产生发送中断
// 供主循环查询UART2是否已产生发送中断,在主循环中处理UART2的中断事件任务,不堵塞其他中断
unsigned char uart2_rxflag = 0;        //定义1个位变量,UART2事件位变量标志,记录UART2已产生接收中断
// 供主循环查询UART2是否已产生接收中断,在主循环中处理UART2的中断事件任务,不堵塞其他中断
unsigned char uart3_txflag = 0;        //定义1个位变量,UART3事件位变量标志,记录UART3已产生发送中断
// 供主循环查询UART3是否已产生发送中断,在主循环中处理UART3的中断事件任务,不堵塞其他中断
unsigned char uart3_rxflag = 0;        //定义1个位变量,UART3事件位变量标志,记录UART3已产生接收中断
// 供主循环查询UART3是否已产生接收中断,在主循环中处理UART3的中断事件任务,不堵塞其他中断
unsigned char uart4_txflag = 0;        //定义1个位变量,UART4事件位变量标志,记录UART4已产生发送中断
// 供主循环查询UART4是否已产生发送中断,在主循环中处理UART1的中断事件任务,不堵塞其他中断
unsigned char uart4_rxflag = 0;        //定义1个位变量,UART4事件位变量标志,记录UART4已产生接收中断
// 供主循环查询UART4是否已产生接收中断,在主循环中处理UART4的中断事件任务,不堵塞其他中断

void Timer0_Init(void)                        //定时器0初始化,2秒@40.000MHz
{
        TM0PS = 0x65;                                //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
        AUXR &= 0x7F;                                //定时器时钟12T模式
        TMOD &= 0xF0;                                //设置定时器模式
        TL0 = 0xB1;                                        //设置定时初始值
        TH0 = 0x00;                                        //设置定时初始值
        TF0 = 0;                                        //清除TF0标志
        TR0 = 1;                                        //定时器0开始计时
        ET0 = 1;                                        //使能定时器0中断
}

void Timer1_Init(void)                        //定时器1初始化,500毫秒@40.000MHz
{
        TM1PS = 0x19;                                //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
        AUXR &= 0xBF;                                //定时器时钟12T模式
        TMOD &= 0x0F;                                //设置定时器模式
        TL1 = 0x99;                                        //设置定时初始值
        TH1 = 0x05;                                        //设置定时初始值
        TF1 = 0;                                        //清除TF1标志
        TR1 = 1;                                        //定时器1开始计时
        ET1 = 1;                                        //使能定时器1中断
}

void Timer3_Init(void)                  //100毫秒@40.000MHz
{
        TM3PS = 0x3D;                          //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
        T4T3M |= 0x02;                          //定时器时钟1T模式
        T3L = 0xFC;                                  //设置定时初始值
        T3H = 0x03;                                  //设置定时初始值
        T4T3M |= 0x08;                          //定时器3开始计时
        IE2 |= 0x20;                          //使能定时器3中断
}

void Timer4_Init(void)                  //200毫秒@40.000MHz
{
        TM4PS = 0x7A;                          //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
        T4T3M |= 0x20;                          //定时器时钟1T模式
        T4L = 0xEF;                                  //设置定时初始值
        T4H = 0x01;                                  //设置定时初始值
        T4T3M |= 0x80;                          //定时器4开始计时
        IE2 |= 0x40;                          //使能定时器4中断
}

void Uart1_Init(void)                        //115200bps@40.000MHz
{
        SCON = 0x50;                                //8位数据,可变波特率
        AUXR |= 0x01;                                //串口1选择定时器2为波特率发生器
        AUXR |= 0x04;                                //定时器时钟1T模式
        T2L = 0xA9;                                        //设置定时初始值
        T2H = 0xFF;                                        //设置定时初始值
        AUXR |= 0x10;                                //定时器2开始计时
        ES = 1;                                                //使能串口1中断
}

void Uart2_Init(void)                        //115200bps@40.000MHz
{
        S2CON = 0x50;                                //8位数据,可变波特率
        AUXR |= 0x04;                                //定时器时钟1T模式
        T2L = 0xA9;                                        //设置定时初始值
        T2H = 0xFF;                                        //设置定时初始值
        AUXR |= 0x10;                                //定时器2开始计时
        IE2 |= 0x01;                                //使能串口2中断
}

void Uart3_Init(void)                        //115200bps@40.000MHz
{
        S3CON = 0x10;                                //8位数据,可变波特率
        S3CON &= 0xBF;                                //串口3选择定时器2为波特率发生器
        AUXR |= 0x04;                                //定时器时钟1T模式
        T2L = 0xA9;                                        //设置定时初始值
        T2H = 0xFF;                                        //设置定时初始值
        AUXR |= 0x10;                                //定时器2开始计时
        IE2 |= 0x08;                                //使能串口3中断
}

void Uart4_Init(void)                        //115200bps@40.000MHz
{
        S4CON = 0x10;                                //8位数据,可变波特率
        S4CON &= 0xBF;                                //串口4选择定时器2为波特率发生器
        AUXR |= 0x04;                                //定时器时钟1T模式
        T2L = 0xA9;                                        //设置定时初始值
        T2H = 0xFF;                                        //设置定时初始值
        AUXR |= 0x10;                                //定时器2开始计时
        IE2 |= 0x10;                                //使能串口4中断
}

void main (void)
{
        P_SW2 |= 0x80;                                //允许访问扩展的特殊寄存器,XFR

                                                                //32位8051需要使用下面3句进行初始化
//        EAXFR = 1;                                        //允许访问扩展的特殊寄存器,XFR
//        WTST = 0;                                        //设置取程序代码等待时间,赋值为0表示不等待,程序以最快速度运行
//        CKCON = 0;                                        //设置访问片内的xdata速度,赋值为0表示用最快速度访问,不增加额外的等待时间

        P0M0 = 0x00; P0M1 = 0x00;         //设置 P0 口为准双向口模式
        P1M0 = 0x00; P1M1 = 0x00;         //设置 P1 口为准双向口模式
        P2M0 = 0x00; P2M1 = 0x00;         //设置 P2 口为准双向口模式
        P3M0 = 0x00; P3M1 = 0x00;        //设置 P3 口为准双向口模式
        P3M0 = 0x00; P3M1 = 0x0c;         //P32、P33设置为高阻输入(需要同步开启上拉电阻)
        P4M0 = 0x00; P4M1 = 0x00;         //设置 P4 口为准双向口模式
        P5M0 = 0x00; P5M1 = 0x00;         //设置 P5 口为准双向口模式
        P6M0 = 0x00; P6M1 = 0x00;         //设置 P6 口为准双向口模式
        P7M0 = 0x00; P7M1 = 0x00;         //设置 P7 口为准双向口模式
       
        P3PU = 0x0c;                                 //P32、P33打开上拉电阻

        int0_flag = 0;                          //初始化用户标志位
        int1_flag = 0;                          //初始化用户标志位
        int2_flag = 0;                          //初始化用户标志位
        int3_flag = 0;                          //初始化用户标志位
   
        t0_flag = 0;                          //初始化用户标志位
        t1_flag = 0;                          //初始化用户标志位
        t3_flag = 0;                          //初始化用户标志位
        t4_flag = 0;                          //初始化用户标志位
   
        uart1_txflag = 0;                        //初始化用户标志位
        uart1_rxflag = 0;                        //初始化用户标志位
        uart2_txflag = 0;                        //初始化用户标志位
        uart2_rxflag = 0;                        //初始化用户标志位
        uart3_txflag = 0;                        //初始化用户标志位
        uart3_rxflag = 0;                        //初始化用户标志位
        uart4_txflag = 0;                        //初始化用户标志位
        uart4_rxflag = 0;                        //初始化用户标志位

        IT0 = 0;                                         //使能 INT0 上升沿和下降沿中断
        //        IT0 = 1;                                 //使能 INT0 下降沿中断
        EX0 = 1;                                         //使能 INT0 中断
        IE0 = 0;                                        //清INT0中断标志

        //        IT1 = 0;                                 //使能 INT1 上升沿和下降沿中断
        IT1 = 1;                                         //使能 INT1 下降沿中断
        EX1 = 1;                                         //使能 INT1 中断
        IE1 = 0;                                        //清INT1中断标志

        INTCLKO |= 0x10;                        //使能INT2中断

        INTCLKO |= 0x20;                        //使能INT3中断
       
        Timer0_Init();                                //调用定时器0初始化函数
        Timer1_Init();                                //调用定时器1初始化函数
        Timer3_Init();                                //调用定时器0初始化函数
        Timer4_Init();                                //调用定时器1初始化函数

        Uart1_Init();                                //调用UART1初始化函数
        Uart2_Init();                                //调用UART2初始化函数
        Uart3_Init();                                //调用UART3初始化函数
        Uart4_Init();                                //调用UART4初始化函数

        EA = 1;                                                //总中断允许位打开
        P40 = 0;                                         //打开LED灯供电
        while(1)                                       //主循环中查询需要处理的各种事件
        {
                /*本演示程序中,主循环查询各中断有无需要继续处理的事件的次序,
                依次是 INTx/TIMERx/UARTx, 用户可以自己根据实际情况,
                调整查询各中断有无需要继续处理的事件的优先次序*/

                //查询外部中断0事件
                if(int0_flag)                        //主循环中查询,INT0是否已产生中断,是否有需要处理的INT 0事件
                {
                        int0_flag = 0;                //清0,INT0事件位变量标志
                        _nop_();                        //用户在此添加需要处理的事件
                        _nop_();
                }

                //查询外部中断1事件
                if(int1_flag)                        //主循环中查询,INT1是否已产生中断,是否有需要处理的INT1事件
                {
                        int1_flag = 0;                //清0,INT1事件位变量标志
                        _nop_();                        //用户在此添加需要处理的事件
                        _nop_();
                }

                //查询外部中断2事件
                if(int2_flag)                        //主循环中查询,INT2是否已产生中断,是否有需要处理的INT2事件
                {
                        int2_flag = 0;                //清0,INT2事件位变量标志
                        _nop_();                        //用户在此添加需要处理的事件
                        _nop_();
                }

                //查询外部中断3事件
                if(int3_flag)                        //主循环中查询,INT3是否已产生中断,是否有需要处理的INT3事件
                {
                        int3_flag = 0;                //清0,INT3事件位变量标志
                        _nop_();                        //用户在此添加需要处理的事件
                        _nop_();
                }

                //查询定时器0中断事件
                if(t0_flag)                                //主循环中查询,定时器0是否已产生中断,是否有需要处理的定时器0事件
                {
                        t0_flag = 0;                //清0,T0事件位变量标志
                        _nop_();                        //用户在此添加需要处理的事件
                        _nop_();
                }

                //查询定时器1中断事件
                if(t1_flag)                                //主循环中查询,定时器1是否已产生中断,是否有需要处理的定时器1事件
                {
                        t1_flag = 0;                //清0,T1事件位变量标志
                        _nop_();                        //用户在此添加需要处理的事件
                        _nop_();
                }

                //查询定时器3中断事件
                if(t3_flag)                                //主循环中查询,定时器3是否已产生中断,是否有需要处理的定时器3事件
                {
                        t3_flag = 0;                //清0,T3事件位变量标志
                        _nop_();                        //用户在此添加需要处理的事件
                        _nop_();
                }

                //查询定时器4中断事件
                if(t4_flag)                                //主循环中查询,定时器4是否已产生中断,是否有需要处理的定时器4事件
                {
                        t4_flag = 0;                //清0,T4事件位变量标志
                        _nop_();                        //用户在此添加需要处理的事件
                        _nop_();
                }

                //查询串口1中断事件
                if(uart1_txflag)                //主循环中查询,UART1是否已产生发送中断,是否有需要处理的UART1发送事件
                {
                        uart1_txflag = 0;        //清0,UART1发送事件位变量标志
                        _nop_();                        //用户在此添加需要处理的事件
                        _nop_();
                }

                if(uart1_rxflag)                //主循环中查询,UART1是否已产生接收中断,是否有需要处理的UART1接收事件
                {
                        uart1_rxflag = 0;        //清0,UART1接收事件位变量标志
                        _nop_();                        //用户在此添加需要处理的事件
                        _nop_();
                }

                //查询串口2中断事件
                if(uart2_txflag)                //主循环中查询,UART2是否已产生发送中断,是否有需要处理的UART2发送事件
                {
                        uart2_txflag = 0;        //清0,UART2发送事件位变量标志
                        _nop_();                        //用户在此添加需要处理的事件
                        _nop_();
                }

                if(uart2_rxflag)                //主循环中查询,UART2是否已产生接收中断,是否有需要处理的UART2接收事件
                {
                        uart2_rxflag = 0;        //清0,UART2接收事件位变量标志
                        _nop_();                        //用户在此添加需要处理的事件
                        _nop_();
                }

                //查询串口3中断事件
                if(uart3_txflag)                //主循环中查询,UART3是否已产生发送中断,是否有需要处理的UART3发送事件
                {
                        uart3_txflag = 0;        //清0,UART3发送事件位变量标志
                        _nop_();                        //用户在此添加需要处理的事件
                        _nop_();
                }

                if(uart3_rxflag)                //主循环中查询,UART3是否已产生接收中断,是否有需要处理的UART3接收事件
                {
                        uart3_rxflag = 0;        //清0,UART3接收事件位变量标志
                        _nop_();                        //用户在此添加需要处理的事件
                        _nop_();
                }

                //查询串口4中断事件
                if(uart4_txflag)                //主循环中查询,UART4是否已产生发送中断,是否有需要处理的UART4发送事件
                {
                        uart4_txflag = 0;        //清0,UART4发送事件位变量标志
                        _nop_();                        //用户在此添加需要处理的事件
                        _nop_();
                }

                if(uart4_rxflag)                //主循环中查询,UART4是否已产生接收中断,是否有需要处理的UART4接收事件
                {
                        uart4_rxflag = 0;        //清0,UART4接收事件位变量标志
                        _nop_();                        //用户在此添加需要处理的事件
                        _nop_();
                }
        }
}


void int0_isr(void) interrupt INT0_VECTOR
{
        _nop_();                                        //特急处理,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
        //以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
        //但时间不要太长,否则会影响其他中断事件的实时响应速度
        int0_flag = 1;                                // int0_flag置1是通知主循环处理部分INT0中断事件不需要特急处理的任务
                                                                //置1,记录INT0已产生中断,供主循环查询判断有无需处理的INT0任务

        if(INT0)                                         //边沿中断,进入后再次判断电平从而判断是什么样的电平
        {
                _nop_();                                //判断为高电平,则当前为上升沿
                _nop_();                                //可以在这里插入断点进行观察现象
        }
        else
        {
                _nop_();                                //判断为低电平,则当前为下降沿
                _nop_();                                //可以在这里插入断点进行观察现象
        }
}
//INT0中断服务程序,INT0_VECTOR在stc8h头文件中已宏定义为0

void int1_isr(void) interrupt INT1_VECTOR
{
        _nop_();                                        //特急处理,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
        //以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
        //但时间不要太长,否则会影响其他中断事件的实时响应速度
        int1_flag = 1;                                // int1_flag置1是通知主循环处理部分INT1中断事件不需要特急处理的任务
}
//INT1中断服务程序,INT1_VECTOR在stc8h头文件中已宏定义为2

void int2_isr(void) interrupt INT2_VECTOR
{
        _nop_();                                        //特急处理,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
        //以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
        //但时间不要太长,否则会影响其他中断事件的实时响应速度
        int2_flag = 1;                                // int2_flag置1是通知主循环处理部分INT2中断事件不需要特急处理的任务
}
//INT2中断服务程序,INT2_VECTOR在stc8h头文件中已宏定义为10

void int3_isr(void) interrupt INT3_VECTOR
{
        _nop_();                                        //特急处理,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
        //以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
        //但时间不要太长,否则会影响其他中断事件的实时响应速度
        int3_flag = 1;                                // int3_flag置1是通知主循环处理部分INT3中断事件不需要特急处理的任务
}
//INT3中断服务程序,INT3_VECTOR在stc8h头文件中已宏定义为11

void Timer0_Isr(void) interrupt TMR0_VECTOR                //定时器0中断服务程序
{
        _nop_();                                        //特急处理,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
        //以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
        //但时间不要太长,否则会影响其他中断事件的实时响应速度
        t0_flag = 1;                                // t0_flag置1是通知主循环处理部分T0中断事件不需要特急处理的任务
                                                                //置1,记录定时器0已产生中断,供主循环查询判断有无需处理的定时器0任务
}
//定时器0中断服务程序,TMR0_VECTOR在stc8h头文件中已宏定义为1

void Timer1_Isr(void) interrupt TMR1_VECTOR
{
        _nop_();                                        //特急处理,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
        //以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
        //但时间不要太长,否则会影响其他中断事件的实时响应速度
        t1_flag = 1;                                // t1_flag置1是通知主循环处理部分T1中断事件不需要特急处理的任务
                                                                //置1,记录定时器1已产生中断,供主循环查询判断有无需处理的定时器1任务
}
//定时器1中断服务程序,TMR1_VECTOR在stc8h头文件中已宏定义为3


void Timer3_Isr(void) interrupt TMR3_VECTOR返回版块
{
        _nop_();                                        //特急处理,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
        //以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
        //但时间不要太长,否则会影响其他中断事件的实时响应速度
        t3_flag = 1;                                // t3_flag置1是通知主循环处理部分T3中断事件不需要特急处理的任务
                                                                //置1,记录定时器3已产生中断,供主循环查询判断有无需处理的定时器1任务
}返回版块
//定时器3中断服务程序,TMR3_VECTOR在stc8h头文件中已宏定义为19

void Timer4_Isr(void) interrupt TMR4_VECTOR
{
        _nop_();                                        //特急处理,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
        //以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
        //但时间不要太长,否则会影响其他中断事件的实时响应速度
        t4_flag = 1;                                // t1_flag置4是通知主循环处理部分T4中断事件不需要特急处理的任务
                                                                //置1,记录定时器4已产生中断,供主循环查询判断有无需处理的定时器1任务
}
//定时器4中断服务程序,TMR4_VECTOR在stc8h头文件中已宏定义为20

void Uart1_Isr(void) interrupt UART1_VECTOR
{
        if (TI)                                                //检测串口1发送中断
        {
                TI = 0;                                        //清除串口1发送中断请求位
                _nop_();                                //特急处理
                //以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
                //但时间不要太长,否则会影响其他中断事件的实时响应速度
                uart1_txflag = 1;                // uart1_txflag置1是通知主循环处理部分串口1发送中断事件不需要特急处理的任务
                                                                //置1,记录UART1已产生发送中断,供主循环查询判断有无需处理的UART1发送任务
        }
        if (RI)                                                //检测串口1接收中断
        {
                RI = 0;                                        //清除串口1接收中断请求位
                _nop_();                                //特急处理
                //以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
                //但时间不要太长,否则会影响其他中断事件的实时响应速度
                uart1_rxflag = 1;                // uart1_rxflag置1是通知主循环处理部分串口1接收中断事件不需要特急处理的任务
                                                                //置1,记录UART1已产生接收中断,供主循环查询判断有无需处理的UART1接收任务
        }
}
//UART1中断服务程序,UART1_VECTOR在stc8h头文件中已宏定义为4

void Uart2_Isr(void) interrupt UART2_VECTOR
{
        if (S2CON & 0x02)                        //检测串口2发送中断
        {
                S2CON &= ~0x02;                        //清除串口2发送中断请求位
                _nop_();                                //特急处理
                //以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
                //但时间不要太长,否则会影响其他中断事件的实时响应速度
                uart2_txflag = 1;                // uart2_txflag置1是通知主循环处理部分串口2发送中断事件不需要特急处理的任务
                                                                //置1,记录UART2已产生发送中断,供主循环查询判断有无需处理的UART2发送任务
        }
        if (S2CON & 0x01)                        //检测串口2接收中断
        {
                S2CON &= ~0x01;                        //清除串口2接收中断请求位
                _nop_();                                //特急处理
                //以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
                //但时间不要太长,否则会影响其他中断事件的实时响应速度
                uart2_rxflag = 1;                // uart2_rxflag置1是通知主循环处理部分串口2接收中断事件不需要特急处理的任务
                                                                //置1,记录UART2已产生接收中断,供主循环查询判断有无需处理的UART2接收任务
        }
}
//UART2中断服务程序,UART2_VECTOR在stc8h头文件中已宏定义为8

void Uart3_Isr(void) interrupt UART3_VECTOR
{
        if (S3CON & 0x02)                        //检测串口3发送中断
        {
                S3CON &= ~0x02;                        //清除串口3发送中断请求位
                _nop_();                                //特急处理
                //以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
                //但时间不要太长,否则会影响其他中断事件的实时响应速度
                uart3_txflag = 1;                // uart3_txflag置1是通知主循环处理部分串口3发送中断事件不需要特急处理的任务
                                                                //置1,记录UART3已产生发送中断,供主循环查询判断有无需处理的UART3发送任务
        }
        if (S3CON & 0x01)                        //检测串口3接收中断
        {
                S3CON &= ~0x01;                        //清除串口3接收中断请求位
                _nop_();                                //特急处理
                //以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
                //但时间不要太长,否则会影响其他中断事件的实时响应速度
                uart3_rxflag = 1;                // uart3_rxflag置1是通知主循环处理部分串口3接收中断事件不需要特急处理的任务
                                                                //置1,记录UART3已产生接收中断,供主循环查询判断有无需处理的UART3接收任务
        }
}
//UART3中断服务程序,UART3_VECTOR在stc8h头文件中已宏定义为17

void Uart4_Isr(void) interrupt UART4_VECTOR
{
        if (S4CON & 0x02)                        //检测串口4发送中断
        {
                S4CON &= ~0x02;                        //清除串口4发送中断请求位
                _nop_();                                //特急处理
                //以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
                //但时间不要太长,否则会影响其他中断事件的实时响应速度
                uart4_txflag = 1;                // uart4_txflag置1是通知主循环处理部分串口4发送中断事件不需要特急处理的任务
                                                                //置1,记录UART4已产生发送中断,供主循环查询判断有无需处理的UART4发送任务
        }
        if (S4CON & 0x01)                        //检测串口4接收中断
        {
                S4CON &= ~0x01;                        //清除串口4接收中断请求位
                _nop_();                                //特急处理
                //以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
                //但时间不要太长,否则会影响其他中断事件的实时响应速度
                uart4_rxflag = 1;                // uart4_rxflag置1是通知主循环处理部分串口4接收中断事件不需要特急处理的任务
                                                                //置1,记录UART4已产生接收中断,供主循环查询判断有无需处理的UART4接收任务
        }
}
//UART4中断服务程序,UART4_VECTOR在stc8h头文件中已宏定义为18


kdusrasf 发表于 前天 13:43

神农鼎 发表于 2025-9-1 12:48
用这个测试程序来修改:




程序测试OK,准备拿另外一个模板来改。谢谢。
页: [1]
查看完整版本: 串口1 用定时器1不工作BUG