发新帖我要提问
12
返回列表
打印

s51单片机串口收发的问题

[复制链接]
楼主: hawk20022002
手机看帖
扫描二维码
随时随地手机跟帖
21
hawk20022002|  楼主 | 2010-5-31 20:44 | 只看该作者 回帖奖励 |倒序浏览
我把void init_serialcom( void ) //串口通信初始设定
{TI=0;  

中断里面也要有清TI的语句吗?

使用特权

评论回复
22
zjswuyunbo| | 2010-5-31 20:59 | 只看该作者
靠,自己思考下!

使用特权

评论回复
23
zjswuyunbo| | 2010-5-31 21:01 | 只看该作者
中断里不要用while(ti).随便看下别人的程序,参考下看看

使用特权

评论回复
24
eshowjow| | 2010-5-31 22:10 | 只看该作者
串口通讯的例子网上很多呢,有这时间讨论,早都抄到一个现成的了,

使用特权

评论回复
25
sxhhhjicbb| | 2010-5-31 23:19 | 只看该作者
可能的二种原因:一,你MCU的波特率和PC的偏差,这是异步采样的。二:你PC端调试软件加了UART结束位检测等功能。

使用特权

评论回复
26
ddxx| | 2010-6-1 08:10 | 只看该作者
给个例子你自己看看。
void sys_Init ( void )  
{
          SCON = 0x50;                              /* mode 1:8bit UART;enable receiver                        */
        PCON |= 0x80;                                                /* SMOD = 1; BR = Timer1 OV                                        */
          TMOD |= 0x20;                              /* timer 1 mode 2: 8-Bit reload                                */
        TMOD &= 0x2f;                                                /* timer0 used by OS in Mode 0                                */
//         TH1   = 0xfd;                              /* F = 11.0592MHz; TH1 = 0xfd; BR =9600                */
        TH1   = 0xf3;                                                /* F = 24MHz; TH1 =0xf3; BR = 9600                        */       

        IP = 0x1f;
          TR1 = 1;                                 /* timer 1 run                                                                */
          ES = 1;                                 /* enable serial port interrupt                                */

        IT0 = 1;               
        IE0 = 0;                                                        /* Clear flag                                                                */

        IT1 = 1;
        IE1 = 0;                                                        /* Clear flag                                                                */

        EX1 = 1;
        EX0 = 1;
       
//        T2MOD = 0x00;

        RCLK = 0;
        TCLK = 0;
        EXEN2 = 0;
        C_T2 = 0;
        CP_RL2 = 0;
        TF2 = 0;
        EXF2 = 0;

        RCAP2L = 0x00;
        RCAP2H = 0xC8;

        TL2 = RCAP2L;
        TH2 = RCAP2H;
                 
        ET2 = 1;                                                        /* Enable Timer2 in Mode 1                                        */

        WDTD = 0xe0;
        WDTC = 0x0f;

        TR2 = 1;

        return;
}

void sp_tx_sem_take ( void )                                                       
{
sp_tx_sem0:
        EA  = 0;
        if ( sp_tx_sem == SEM_FULL )
        {
                EA = 1;
                os_wait ( K_TMO, 1, 0 );
                goto sp_tx_sem0;
        }

           sp_tx_sem = SEM_FULL;
        EA = 1;
        return;
}

void sp_tx_sem_give ( void )                                                       
{
        EA = 0;
        sp_tx_sem = SEM_EMPTY;
        EA = 1;
        return;                                                                                        // OK                                                               
}

void sp_tx_start ( void )
{
        SBUF = SP_STX;        
        return;
}

void sp_rx_sem_give ( void )                                                       
{
        EA = 0;
        sp_rx_sem = SEM_EMPTY;
        sp_rx_len = 0;
        EA = 1;
        return;                                                                                        // OK                                                               
}
void serial_int ( void ) interrupt 4 using 2
{
        static unsigned char rx_cnt = 0;                /* State: idle, initial state                                         */
        static unsigned char tx_cnt = 0;

        if ( TI )
        {
                if ( sp_tx_sem == SEM_FULL )
                        {       
                        switch ( tx_cnt )
                        {
                        case 0x00:
                                tx_cnt ++;
                                SBUF = SP_ADDR_DVR;
                                break;
                        case 0x01:
                                tx_cnt ++;
                                SBUF = sp_tx_addr;
                                break;
                        case 0x02:
                                tx_cnt ++;
                                SBUF = sp_tx_cmd;
                                break;
                        case 0x03:                                  
                                if ( sp_tx_len > 0 )
                                {       
                                        sp_tx_len --;                               
                                        SBUF = sp_tx_buffer [ sp_tx_len ];
                                }
                                if ( sp_tx_len == 0 )
                                tx_cnt ++;
                                break;
                        case 0x04:
                                tx_cnt ++;
                                SBUF = SP_ETX;
                                break;
                        default:
                                tx_cnt = 0x00;
                                sp_tx_len = 0x00;
                                sp_tx_sem_give ();                                /* Transmission Complete, Release Semaphore                */
                                break;
                        }
                        TI = 0;                                                                        /* Clear Interrupt Flag                                                 */
                }
        }

           if ( RI )                                                                        /* Receive interrupt, clear flag RI, handled        */                                                                       
        {       
                if ( sp_rx_sem == SEM_EMPTY )
                {
                        switch ( rx_cnt )
                        {
                                 case 0x00 :
                                        if ( SBUF == SP_ADDR_KB )
                                                rx_cnt = 0x01;
                                        else
                                                rx_cnt = 0x00;
                                        break;
                                 case 0x01 :
                                        if ( SBUF == SP_ADDR_DVR )
                                                rx_cnt = 0x02;
                                          else
                                                rx_cnt = 0x00;
                                        break;
                                 case 0x02 :
                                        if ( SBUF == SP_STX )
                                        {
                                                rx_cnt = 0x00;
                                                   break;
                                        }                       
                                        sp_rx_cmd = SBUF;
                                        rx_cnt = 0x03;
                                        break;
                                 case 0x03 :
                                        if ( SBUF == SP_STX )
                                        {
                                                rx_cnt = 0x00;
                                                sp_rx_len = 0x00;
                                                   break;
                                        }
                                        if ( SBUF == SP_ETX )
                                        {
                                                rx_cnt = 0x00;
                                                sp_rx_sem = SEM_FULL;
                                                isr_send_signal ( SP_RX );
                                        }
                                        else
                                        {               
                                                sp_rx_buffer [ sp_rx_len ] = SBUF;
                                                sp_rx_len ++;
                                        }
                                        break;
                                default :                                                        /* Machine state return idle state                                */
                                        rx_cnt = 0x00;
                                        sp_rx_len = 0x00;
                                         break;
                        }
                }
                RI = 0;                                                                                /* Clear Interrupt Flag                                                        */
        }
        return;                       
}

使用特权

评论回复
27
冷漠| | 2010-6-1 08:48 | 只看该作者
本帖最后由 冷漠 于 2010-6-1 08:51 编辑
我用S51 单片机做的程序片段如下:用的是22。1184M晶振
void init_serialcom( void ) //串口通信初始设定
   {
    SCON = 0x50 ;   //UART为模式1,8位数据,允许接收
    TMOD |= 0x20 ; //定时器1为模式2,8位自动重装
    PCON |= 0x80 ; //SMOD=1;
//    TH1 = 0xFA ;   //Baud:19200 fosc="11".0592MHz
TH1=0XF4  ;      //9600    22.1184m      // ? ??
   IE |= 0x90 ;   //Enable Serial Interrupt
    TR1 = 1 ;       // timer 1 run
      TI=1;

       }



9600/22.1184,应该TH1=0xFD!
TH1=0XFD  ;      //9600    22.1184m

使用特权

评论回复
28
hawk20022002|  楼主 | 2010-6-1 09:07 | 只看该作者
LS的是不是算错了。

使用特权

评论回复
29
冷漠| | 2010-6-1 09:28 | 只看该作者
对不起:又算了一下,下面0xF4是对的。
TH1=0XF4  ;      //9600    22.1184m    // 正确

使用特权

评论回复
30
一棵小草| | 2010-6-1 13:11 | 只看该作者
我把void init_serialcom( void ) //串口通信初始设定
{TI=0;  

中断里面也要有清TI的语句吗?
hawk20022002 发表于 2010-5-31 20:44


就按照这个改,中断中不用清零了,再试试。

因为我认为,你的中断让TI =0;
而你的send----当中,while(TI == 0);TI =0;因为中断中已经清零了,那么这里就可能死循环。

使用特权

评论回复
31
hawk20022002|  楼主 | 2010-6-1 13:15 | 只看该作者
现在改了之后是收到什么数据发什么数据,但是偶尔会出现发送一帧数据给单片机,比如有77个,但是调试助手收到的77个数据是2帧,数据都没错就是按2帧发送回来的。

使用特权

评论回复
32
hawk20022002|  楼主 | 2010-6-1 15:44 | 只看该作者
搞定了。。。谢谢大家

使用特权

评论回复
33
zj198828| | 2010-6-1 16:44 | 只看该作者
SCON  = 0x50;                        /* SCON: 模式 1, 8-bit UART, 使能接收         */
    TMOD |= 0x20;               /* TMOD: timer 1, mode 2, 8-bit reload        */
    TH1   = 0xFD;               /* TH1:  reload value for 9600 baud @ 11.0592MHz   */
    TR1   = 1;                  /* TR1:  timer 1 run                          */
    EA    = 1;                  /*打开总中断*/
    ES    = 1;                  /*打开串口中断*/

while (1)                       /*主循环不做任何动作*/
    {
    }
}

void UART_SER (void) interrupt 4 //串行中断服务程序
{
    unsigned char Temp;          //定义临时变量
   
   if(RI)                        //判断是接收中断产生
     {
          RI=0;                      //标志位清零
          Temp=SBUF;                 //读入缓冲区的值
          P1=Temp;                   //把值输出到P1口,用于观察
      SBUF=Temp;                 //把接收到的值再发回电脑端
         }
   if(TI)                        //如果是发送标志位,清零
     TI=0;
}

使用特权

评论回复
34
zj198828| | 2010-6-1 16:45 | 只看该作者
SCON  = 0x50;                        /* SCON: 模式 1, 8-bit UART, 使能接收         */
    TMOD |= 0x20;               /* TMOD: timer 1, mode 2, 8-bit reload        */
    TH1   = 0xFD;               /* TH1:  reload value for 9600 baud @ 11.0592MHz   */
    TR1   = 1;                  /* TR1:  timer 1 run                          */
    EA    = 1;                  /*打开总中断*/
    ES    = 1;                  /*打开串口中断*/

while (1)                       /*主循环不做任何动作*/
    {
    }
}

void UART_SER (void) interrupt 4 //串行中断服务程序
{
    unsigned char Temp;          //定义临时变量
   
   if(RI)                        //判断是接收中断产生
     {
          RI=0;                      //标志位清零
          Temp=SBUF;                 //读入缓冲区的值
          P1=Temp;                   //把值输出到P1口,用于观察
      SBUF=Temp;                 //把接收到的值再发回电脑端
         }
   if(TI)                        //如果是发送标志位,清零
     TI=0;
}

使用特权

评论回复
35
hanfei08131106| | 2010-6-1 22:50 | 只看该作者
同意18楼

使用特权

评论回复
36
lhbdyx1| | 2010-9-9 16:02 | 只看该作者
跟着学

使用特权

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

本版积分规则