最近使用c8051做开发,串口程序移入工程时,整个程序竟然不跑了,加断点,调试,发现在串口查询发送出了问题,程序在查询发送完毕的时候,竟然死在这,就是while(TI0==0)这地方,用其它型号单片机没有这种情况,c8051F120单片机强大无比,但也复杂,用起来不顺手,下面就搜集了有关串口中断发送的资料,改为中断发送解决程序死的问题。

    有关串口发送的程序例子:

 
  
  1. 假设要发送一组数据   Send[10]  
  2. 一般采用查询发送(循环发送)方式:  
  3. unsigned char Send[10];                  //发送量  
  4. unsigned char i;                         //循环量  
  5. for(i = 0; i < 10; i++)  
  6. {  
  7.     SBUF = Send[i];                   //发送  
  8.     while(TI == 0);                   //等待发送完成  
  9.     TI = 0;                           //清标志  
  10. }  
  11.   
  12. 采用中断发送方式:  
  13. unsigned char Send[10];                  //发送量  
  14. unsigned char num;                       //发送数据量  
  15. unsigned char *p;                        //发送用指针  
  16.   
  17. //发送时:  
  18. num = 10;                                //定义发送数据量  
  19. p = &Send ;                              //取首地址  
  20. SBUF = *p;                               //发送第一个数据,启动发送中断  
  21. //中断代码:  
  22. void ComInt() interrupt 4  
  23. {  
  24.     if(RI)  RI = 0;                   //接收中断略;  
  25.   
  26.     if(TI)                            //发送中断处理  
  27.     {  
  28.         TI = 0;                    //清标志  
  29.         num--;                     //计数减1  
  30.         p++;                       //指针加1  
  31.         if(num > 0) SBUF = *p;     //数据继续发送至全部发完  
  32.     }  
  33. }  

对这个程序例子,网上给出这样的评价:

中断发送优点:省去循环等待时间,以上面例子为例,9600bps时查询发送约占用单片机10ms多,而中断发送只占单片机几十微秒(单片机速度 越快,占用时间越少)。 

 
  
  1. #include <c8051f120.h>                 // SFR declarations 
  2. #include <stdio.h>                      
  3.  
  4. //----------------------------------------------------------------------------- 
  5. // 16-bit SFR Definitions for 'F12x 
  6. //----------------------------------------------------------------------------- 
  7.  
  8. sfr16 RCAP2    = 0xca;                 // Timer2 capture/reload 
  9. sfr16 TMR2     = 0xcc;                 // Timer2 
  10.  
  11. //----------------------------------------------------------------------------- 
  12. // Global Constants 
  13. //----------------------------------------------------------------------------- 
  14.  
  15. #define BAUDRATE     115200            // Baud rate of UART in bps 
  16.  
  17. // SYSTEMCLOCK = System clock frequency in Hz 
  18. #define SYSTEMCLOCK       (22118400L * 9 / 4) 
  19.  
  20. //----------------------------------------------------------------------------- 
  21. // Function Prototypes 
  22. //----------------------------------------------------------------------------- 
  23.  
  24. void OSCILLATOR_Init (void);          
  25. void PORT_Init (void); 
  26. void UART0_Init (void); 
  27.  
  28. //----------------------------------------------------------------------------- 
  29. // Global Variables 
  30. //----------------------------------------------------------------------------- 
  31.  
  32. #define UART_BUFFERSIZE 64 
  33. unsigned char UART_Buffer[UART_BUFFERSIZE]; 
  34. unsigned char UART_Buffer_Size = 0;  
  35. unsigned char UART_Input_First = 0
  36. unsigned char UART_Output_First = 0
  37. unsigned char TX_Ready =1
  38. static char Byte; 
  39.  
  40. //----------------------------------------------------------------------------- 
  41. // main() Routine 
  42. //----------------------------------------------------------------------------- 
  43.  
  44. void main (void) 
  45.       
  46.    SFRPAGE = CONFIG_PAGE
  47.  
  48.    WDTCN = 0xDE;                       // Disable watchdog timer 
  49.    WDTCN = 0xAD
  50.  
  51.    OSCILLATOR_Init ();                 // Initialize oscillator 
  52.    PORT_Init ();                       // Initialize crossbar and GPIO 
  53.  
  54.    UART0_Init ();                      // Initialize UART0 
  55.     
  56.    EA = 1
  57.  
  58.    SFRPAGE = UART0_PAGE;    
  59.  
  60.    while (1) 
  61.    {   
  62.       // If the complete word has been entered via the terminal followed  
  63.       // by carriage return 
  64.       if((TX_Ready == 1) && (UART_Buffer_Size != 0) && (Byte == 13))   
  65.       {  
  66.          TX_Ready = 0;                  // Set the flag to zero 
  67.          TI0 = 1;                       // Sed 
  68.    } 
  69.  
  70. //----------------------------------------------------------------------------- 
  71. // Initialization Subroutines 
  72. //----------------------------------------------------------------------------- 
  73.  
  74. //----------------------------------------------------------------------------- 
  75. // OSCILLATOR_Init 
  76. //----------------------------------------------------------------------------- 
  77. // 
  78. // Return Value : None 
  79. // Parameters   : None 
  80. // 
  81. // This function initializes the system clock to use the PLL as its clock 
  82. // source, where the PLL multiplies the external 22.1184MHz crystal by 9/4. 
  83. // 
  84. //----------------------------------------------------------------------------- 
  85. void OSCILLATOR_Init (void) 
  86.    int i;                              // Software timer 
  87.  
  88.    char SFRPAGESFRPAGE_SAVE = SFRPAGE;        // Save Current SFR page 
  89.  
  90.    SFRPAGE = CONFIG_PAGE;              // Set SFR page 
  91.  
  92.    OSCICN = 0x80;                      // Set internal oscillator to run 
  93.                                        // at its slowest frequency 
  94.  
  95.    CLKSEL = 0x00;                      // Select the internal osc. as 
  96.                                        // the SYSTEMCLOCK source 
  97.  
  98.    // Initialize external crystal oscillator to use 22.1184 MHz crystal 
  99.  
  100.    OSCXCN = 0x67;                      // Enable external crystal osc. 
  101.    for (i=0; i < 256; i++);            // Wait at least 1ms 
  102.  
  103.    while (!(OSCXCN & 0x80));           // Wait for crystal osc to settle 
  104.  
  105.    SFRPAGE = LEGACY_PAGE
  106.    FLSCL |=  0x30;                     // Initially set FLASH read timing for 
  107.                                        // 100MHz SYSTEMCLOCK (most conservative 
  108.                                        // setting) 
  109.    if (SYSTEMCLOCK <= 25000000) {            
  110.    // Set FLASH read timing for <=25MHz 
  111.       FLSCL &= ~0x30; 
  112.    } else if (SYSTEMCLOCK <= 50000000) {     
  113.    // Set FLASH read timing for <=50MHz 
  114.       FLSCL &= ~0x20; 
  115.    } else if (SYSTEMCLOCK <= 75000000) {     
  116.    // Set FLASH read timing for <=75MHz 
  117.       FLSCL &= ~0x10; 
  118.    } else {                            // set FLASH read timing for <=100MHz 
  119.       FLSCL &= ~0x00; 
  120.    } 
  121.  
  122.    // Start PLL for 50MHz operation 
  123.    SFRPAGE = PLL0_PAGE
  124.    PLL0CN = 0x04;                      // Select EXTOSC as clk source 
  125.    PLL0CN |= 0x01;                     // Enable PLL power 
  126.    PLL0DIV = 0x04;                     // Divide by 4 
  127.    PLL0FLT &= ~0x0f; 
  128.    PLL0FLT |=  0x0f;                   // Set Loop Filt for (22/4)MHz input clock 
  129.    PLL0FLT &= ~0x30;                   // Set ICO for 30-60MHz 
  130.    PLL0FLT |=  0x10; 
  131.  
  132.    PLL0MUL = 0x09;                     // Multiply by 9 
  133.  
  134.    // wait at least 5us 
  135.    for (i = 0; i < 256; i++) ; 
  136.  
  137.    PLL0CN |= 0x02;                     // Enable PLL 
  138.  
  139.    while (PLL0CN & 0x10 == 0x00);      // Wait for PLL to lock 
  140.  
  141.    SFRPAGE = CONFIG_PAGE
  142.  
  143.    CLKSEL = 0x02;                      // Select PLL as SYSTEMCLOCK source 
  144.  
  145.    SFRPAGE = SFRPAGE_SAVE;             // Restore SFRPAGE 
  146.  
  147.  
  148. //----------------------------------------------------------------------------- 
  149. // PORT_Init 
  150. //----------------------------------------------------------------------------- 
  151. // 
  152. // Return Value : None 
  153. // Parameters   : None 
  154. // 
  155. // This function configures the crossbar and GPIO ports. 
  156. // 
  157. // P0.0   digital   push-pull     UART TX 
  158. // P0.1   digital   open-drain    UART RX 
  159. //----------------------------------------------------------------------------- 
  160. void PORT_Init (void) 
  161.    char SFRPAGESFRPAGE_SAVE = SFRPAGE;        // Save Current SFR page 
  162.  
  163.    SFRPAGE = CONFIG_PAGE;              // Set SFR page 
  164.  
  165.    XBR0     = 0x04;                    // Enable UART0 
  166.    XBR1     = 0x00
  167.    XBR2     = 0x40;                    // Enable crossbar and weak pull-up 
  168.                                         
  169.  
  170.    P0MDOUT |= 0x01;                    // Set TX pin to push-pull 
  171.    P1MDOUT |= 0x40;                    // Set P1.6(LED) to push-pull 
  172.  
  173.    SFRPAGE = SFRPAGE_SAVE;             // Restore SFR page 
  174.  
  175.  
  176. //----------------------------------------------------------------------------- 
  177. // UART0_Init   Variable baud rate, Timer 2, 8-N-1 
  178. //----------------------------------------------------------------------------- 
  179. // 
  180. // Return Value : None 
  181. // Parameters   : None 
  182. // 
  183. // Configure UART0 for operation at <baudrate> 8-N-1 using Timer2 as 
  184. // baud rate source. 
  185. // 
  186. //----------------------------------------------------------------------------- 
  187. void UART0_Init (void) 
  188.    char SFRPAGE_SAVE; 
  189.  
  190.    SFRPAGESFRPAGE_SAVE = SFRPAGE;             // Preserve SFRPAGE 
  191.  
  192.    SFRPAGE = TMR2_PAGE
  193.  
  194.    TMR2CN = 0x00;                      // Timer in 16-bit auto-reload up timer 
  195.                                        // mode 
  196.    TMR2CF = 0x08;                      // SYSCLK is time base; no output; 
  197.                                        // up count only 
  198.    RCAP2 = - ((long) SYSTEMCLOCK/BAUDRATE/16); 
  199.    TMR2 = RCAP2
  200.    TR21;                             // Start Timer2 
  201.  
  202.    SFRPAGE = UART0_PAGE
  203.  
  204.    SCON0 = 0x50;                       // 8-bit variable baud rate; 
  205.                                        // 9th bit ignored; RX enabled 
  206.                                        // clear all flags 
  207.    SSTA0 = 0x15;                       // Clear all flags; enable baud rate 
  208.                                        // doubler (not relevant for these 
  209.                                        // timers); 
  210.                                        // Use Timer2 as RX and TX baud rate 
  211.                                        // source; 
  212.    ES0 = 1;   
  213.    IP |= 0x10; 
  214.  
  215.    SFRPAGE = SFRPAGE_SAVE;             // Restore SFRPAGE 
  216.  
  217.  
  218. //----------------------------------------------------------------------------- 
  219. // Interrupt Service Routines 
  220. //----------------------------------------------------------------------------- 
  221.  
  222. //----------------------------------------------------------------------------- 
  223. // UART0_Interrupt 
  224. //----------------------------------------------------------------------------- 
  225. // 
  226. // This routine is invoked whenever a character is entered or displayed on the 
  227. // Hyperterminal. 
  228. // 
  229. //----------------------------------------------------------------------------- 
  230.  
  231. void UART0_Interrupt (void) interrupt 4 
  232.    SFRPAGE = UART0_PAGE
  233.  
  234.    if (RI0 == 1) 
  235.    { 
  236.       if( UART_Buffer_Size == 0)  {      // If new word is entered 
  237.          UART_Input_First = 0;    } 
  238.  
  239.       RI0 = 0;                           // Clear interrupt flag 
  240.  
  241.       Byte = SBUF0;                      // Read a character from UART 
  242.  
  243.       if (UART_Buffer_Size < UART_BUFFERSIZE
  244.       { 
  245.          UART_Buffer[UART_Input_First] = Byte; // Store in array 
  246.  
  247.          UART_Buffer_Size++;             // Update array's size 
  248.  
  249.          UART_Input_First++;             // Update counter 
  250.       } 
  251.    } 
  252.  
  253.    if (TI0 == 1)                   // Check if transmit flag is set 
  254.    { 
  255.       TI0 = 0;                           // Clear interrupt flag 
  256.  
  257.       if (UART_Buffer_Size != 1)         // If buffer not empty 
  258.       { 
  259.          // If a new word is being output 
  260.          if ( UART_Buffer_Size == UART_Input_First ) { 
  261.               UART_Output_First = 0;  } 
  262.  
  263.          // Store a character in the variable byte 
  264.          Byte = UART_Buffer[UART_Output_First]; 
  265.  
  266.          if ((Byte >= 0x61) && (Byte <= 0x7A)) { // If upper case letter 
  267.             Byte -32; } 
  268.  
  269.          SBUF0 = Byte;                   // Transmit to Hyperterminal 
  270.  
  271.          UART_Output_First++;            // Update counter 
  272.  
  273.          UART_Buffer_Size--;             // Decrease array size 
  274.  
  275.       } 
  276.       else 
  277.       { 
  278.          UART_Buffer_Size = 0;            // Set the array size to 0 
  279.          TX_Ready = 1;                    // Indicate transmission complete 
  280.       } 
  281.    } 
  282.  
  283. //----------------------------------------------------------------------------- 
  284. // End Of File 
  285. //----------------------------------------------------------------------------- 

  看看人家例程,说得很明白,中断式接收和发送,好好读读人家程序,不错的。