打印

PCA UART 在P89V51RD2 的移植问题

[复制链接]
1926|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
chuandaoxy|  楼主 | 2009-6-29 00:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
pca 制作 soft uart 具有一定的优势,(微型系统小数据量传输),成本低联,当然他的弱点也很明显,就是占用资源,公司的工程师在 

新华龙的芯片上成功应用了这项技术,我在网上偶然发现p89v51rd2也具有pca阵列,于是想移植到其上,但是发现了一个问题,有可能是 

对芯片掌握不够造成的,希望大家指点迷津,下面是我的代码,测试是在stc的下在板上进行的,经振18.432m,程序的关键部分是,数据发 

送过程的模拟,以状态机的形式在程序里体现,在软串口的应用上使用了大量标志位,实际上和硬件uart是一致的,PCA模块1是发送模块 

我的ccf1标志位始终不能被手动清零,程序就是发送11个数据,我的软串口上拉了一个LED,发送时应该闪亮,可是他一直亮,说明数据没有发送 

下面是我的代码大家分析一下,错在那里? 

//设计要求实现普通96/n/8/1通信10位数据 V1
//实现全双工,使用cex0,cex1

#include <REG51F.h>
#include <stdio.h>

#define uchar unsigned char
#define uint  unsigned int

#define BAUD_RATE     9600              // Baud rate of UART in bps

#define SYSCLK        18432000          // SYSCLK frequency in Hz

#define TIME_COUNT SYSCLK/BAUD_RATE/6     // 对应一个位时间的PCA计数值(PCA 配置为对SYSCLK/6计数)

#define TH_TIME_COUNT TIME_COUNT*3/2      // 3/2位时间用于接收到一个起始位后在起始位边沿之后RX应在一个

bit SRI1;                                 // SW_UART 接收完成标志
bit STI1;                                 // SW_UART 发送完成标志

bit    SREN;                                // SW_UART 用户级中断支持允许
bit SES1; 
                                

bit SREN1;                                 // SW_UART 接收允许
bit STXBSY1;                             // SW_UART 发送忙标志

bit SW_DONE;                            //发送完15个数据标志

sbit SW1_RX = P1^3;                     // SW_UART 接收
sbit SW1_TX = P1^4;                     // SW_UART 发送

sbit   tt = P3^3; 

#define Uart1Tbuf_RAM             0x0E00

uchar SW_Uart1TNum;


uchar  TDR1;                             // SW_UART 发送数据寄存器
uchar  RDR1;                             // SW_UART 接收数据寄存器

uchar SUTXST1 = 0;                         // SW_UART TX状态变量
uchar SURXST1 = 0;                         // SW_UART RX状态变量

uchar RXSHIFT1= 0;                         // SW_UART RX移位寄存器


void PCA_ISR();                         // SW_UART 中断服务程序
void PCA_TEST(void);                     // SW_UART 中断方式测试程序
void USER_ISR(void);                     // SW_UART 测试中断服务程序
void SW_UART_INIT();                     // SW_UART 初始化程序
void SW_UART_ENABLE();                     // SW_UART 允许程序


/************************************************************************/

void SW_UART_INIT(void)                     

{
                                         
    

    CCON    = 0x00;                      
    
                                        
    CMOD   |= 0x02;                         
      CCAPM0  = 0x10;

    CCAP0L = 0x00;
       CCAP0H = 0x00;

    

    CCF0 = 0;                              // 清除被挂起的PCA模块0和模块1捕捉/比较中断
    CCF1 = 0;    
                             
    SRI1 = 0;                              // 清除接收完成标志
    STI1 = 0;                              // 清除发送完成标志

    SW1_TX  = 1;                          // TX线初始化为高电平
    STXBSY1 = 0;                          // 清除SW_UART忙标志
    
}

/************************************************************************/

 void SW_UART_ENABLE(void)                  //ok

{
   
    CCAPM0 |= 0x01;                       // 允许PCA模块0接收中断
    CCAPM1 |= 0x01;                       // 允许PCA模块1发送中断

    CR    = 1;                               // 启动PCA计数器


    IE = IE | 0x40; 
   
}


/************************************************************************/

 PCA_ISR() interrupt 6 using 1


{
    unsigned int PCA_TEMP;                           // 临时存储变量用于处理PCA模快高和低字节

    if (CCF0)                                     // 首先检查接收中断变量如果CCF0置位则对其服务
    
    {                                    
         CCF0 = 0;                                  // 清除中断标志

        /***************************************************************************************/

        if (SURXST1==0){                         //状态0

            if (SREN1 && (SW1_RX==0))             //检查接收允许和起始位是否正确
            
            {              
                PCA_TEMP = (CCAP0H << 8);        // 将模块0内容读到
                PCA_TEMP |= CCAP0L;              // PCA_TEMP
                PCA_TEMP += TH_TIME_COUNT;          // 加3/2位时间到PCA_TEMP
                CCAP0L = PCA_TEMP;                  // 用新值恢复PCA0CPL0和PCA0CPH0
                CCAP0H = (PCA_TEMP >> 8);
                CCAPM0 = 0x49;                      // 将模块0切换到软件定时器方式允许中断
                SURXST1++;                          // 更新RX状态变量
            }
        }

        /***************************************************************************************/

        else if (SURXST1==9)                      //状态9
        {
            RDR1 = RXSHIFT1;                      // 将接收到的数据传送到接收寄存器
            SRI1 = 1;                              // 置1接收完成标志
            CCAPM0  = 0x11;                      // 切换模块0到负沿捕捉方式允许中断以检测起始位
            SURXST1 = 0;                          // 复位RX状态变量
            if (SES1){                              // 如果用户级中断支持被允许
                IE |= 0x84;                      // 通过允许并强制 模拟UART发送中断(借用外部中断1)
                 tt =0;                             // 外部中断激活(测试通过)
            }                                     // 可将硬件P3^3直接接地(未测)需要考虑。。。。
        }

        /***************************************************************************************/
                                                 
        else if (SURXST1<9)                          //状态1-8
        {
            RXSHIFT1 = RXSHIFT1 >> 1;              // 右移一位
            if (SW1_RX==1)                          // If SW0_RX=1
            {
                RXSHIFT1 |= 0x80;                  // 将'1'移入RXSHIFT的msb
            }
            else
            {
                RXSHIFT1 &= ~0x80;             // 将'1'移入RXSHIFT的msb
            }
            PCA_TEMP = (CCAP0H << 8);        // 将模块0内容读到PCA_TEMP
            PCA_TEMP |= CCAP0L; 
            PCA_TEMP += TIME_COUNT;         // 加一个位时间到PCA_TEMP
            CCAP0L  = PCA_TEMP;             // 用新值恢复PCA0CPL0和PCA0CPH0
            CCAP0H  = (PCA_TEMP >> 8);
            SURXST1++;                         // 更新RX状态变量
        }

        /***************************************************************************************/
     
        else    // 出错处理
        {
            CCAPM0 = 0x11;                 // 切换模块0到负沿捕捉方式允许中断以检测起始位
            SURXST1=0;
        }
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    else if (CCF1){                            // 检查发送中断如果CCF3置位则对其服务

        CCF1 = 0;                             // 清除中断标志

        /***************************************************************************************/

        if (SUTXST1==0)
        
        {
            SW1_TX = 0;                     // 使TX引脚变低作为起始位
            PCA_TEMP = CCAP0L;                 // 将PCA计数器的值读到PCA_TEMP
            PCA_TEMP |= (CCAP0H<< 8);
            PCA_TEMP += TIME_COUNT;         // 加一个位时间
            CCAP1L = PCA_TEMP;             // 将更新后的匹配值存到
            CCAP1H = (PCA_TEMP >> 8);        // 模块1捕捉比较寄存器
            CCAPM1 |= 0x48;                 // 允许模块1软件定时器
            SUTXST1++;                         // 更新TX状态变量
        }

        /***************************************************************************************/

        else if(SUTXST1==11)
        {
            STI1 = 1;                         // 表示发送完成
            SUTXST1 = 0;                     // 复位TX状态
            SW1_TX = 1;                     // SW_TX应保持高电平
            CCAPM1 = 0x01;                     // 禁止模块1软件定时器保持中断为允许状态以备下一次传输
            if (SES1){                         //如果用户级中断支持被允许:
                IE |= 0x84;                 // 通过允许并强制 模拟UART发送中断(借用外部中断1)
                 tt =0;                             // 外部中断激活(测试通过)
            }
            STXBSY1 = 0;                     // SW_UART TX空闲
        }
        
        
        /***************************************************************************************/
            
        else if(SUTXST1==10)                // 发送停止位
        {
            SW1_TX = 1;                     // 输出停止位 1
            PCA_TEMP = (CCAP1H  << 8);        // 将模块1内容读到PCA_TEMP
            PCA_TEMP |= CCAP1L;
            PCA_TEMP += TIME_COUNT;         // 加一个位时间到PCA_TEMP
            CCAP1L  = PCA_TEMP;             // 用新值恢复PCA0CPL1
            CCAP1H  = (PCA_TEMP >> 8);        // 和PCA0CPH1
            SUTXST1++;                         // 更新TX状态变量
        }

           /***************************************************************************************/

        else if(SUTXST1<10)
        {
            SW1_TX = (TDR1 & 0x01);         // 将TDR的LSB输出到SW_TX引脚
            TDR1 >>= 1;                     // TDR右移一位
        
                        // 将一个'1'移入TDR的MSB作为状态9的停止位
            PCA_TEMP = (CCAP1H << 8);        // 将模块1内容读到PCA_TEMP
            PCA_TEMP |= CCAP1L;
            PCA_TEMP += TIME_COUNT;         // 加一个位时间到PCA_TEMP
            CCAP1L = PCA_TEMP;             // 用新值恢复PCA0CPL1
            CCAP1H = (PCA_TEMP >> 8);        // 和PCA0CPH1
            SUTXST1++;                         // 更新TX状态变量
        }
        else                // 出错处理
        {
            SUTXST1 = 0;                     // 复位TX状态
            SW1_TX = 1;                     // SW_TX应保持高电平
            CCAPM1 = 0x01;                 // 禁止模块1软件定时器保持中断为允许状态以备下一次传输
        }
    }
    CF=0;
}

 
void PCA_START(void)
{
    SW_UART_INIT();                     // 初始化SW_UART
    SW_UART_ENABLE();                     // 允许SW_UART


    CCAPM1  = 0x48;
    CCAP1L = 0x00;
    CCAP1H = 0x00;    
    EA=1;
    SES1 = 1;                             // 允许用户级中断支持
    STI1=1;                             // 指示发送完成以启动下一次传输
    SREN1 = 1;                             // 允许SW_UART接收器
    IE |= 0x84; 
                    
      tt =0;
}     



//void SW_UART_ISR(void) interrupt 11        // 借用比较器0中断!!! 
  USER_ISR()   interrupt 2
{
    uchar xdata *Read_Buff;
    
      IE &= 0x80;     
        if (STI1){ 
        STI1 = 0;                             // 清楚发送标志
        Read_Buff=Uart1Tbuf_RAM;
        
            STXBSY1 = 1;                     // 申请SW_UART发送器
            TDR1=Read_Buff[SW_Uart1TNum];    //将串口0发送缓存中的一个字节
            SW_Uart1TNum--;
            CCF1 = 1;             // 强制模块1中断以启动发送
            
        }


    if (STI1|SRI1)                 // 如果SRI或STI置位再次触发
    {    //    STI1 = 0;     
    

        IE |= 0x84;                 
         tt =0;
    }
    else
    {
    
        IE = 0x00;                 
         tt =1;

    }
}        

 READ_MK_DATA(){                //  获取数据命令 
    uchar data i;
    uchar xdata *Sent_Buff;
    Sent_Buff=Uart1Tbuf_RAM;
    Sent_Buff[0]=0X7E;
    
    Sent_Buff[1]=0X30;
    Sent_Buff[2]=0X31;
    Sent_Buff[5]=0X31;                
    Sent_Buff[6]=0X31;
    
    Sent_Buff[7]=0X20;
    Sent_Buff[8]=0X20;
    Sent_Buff[9]=0X20;
    Sent_Buff[10]=0X20;
    

    SW_Uart1TNum=11;
    STI1=1;
    IE |= 0x84;                 
      tt =0;
}

  





 main( )

{  

   IP=0x40;

   

   PCA_START();

 

 READ_MK_DATA();

   while(1)

{}

}

相关帖子

沙发
古道热肠| | 2009-6-29 11:23 | 只看该作者

用软仿真吧,Keil支持这个模块的.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

855

主题

1044

帖子

4

粉丝