×
嵌入式 > 技术百科 > 详情

Freescale 9S12 系列单片机应用笔记(SCI)1

发布时间:2020-05-28 发布时间:
|

SCI 模块应用笔记(1)

UART,也就是异步串行通讯接口是单片机中最常见的外设,几乎每种类型的单片机都必备1到2个UART 接口,9S12 系列单片机也不例外。不过,摩托罗拉给他自己的单片机的串口起了个很有个性的缩写名称SCI (serial communication interface),其实就是我们常说的 UART。

各种单片机串口的编程都大同小异,无非就是设置波特率、起始位、停止位、校验位等等。下面通过给出编程例子的方式分别介绍。

设置波特率

 
  1. /** 
  2.  * Set the Baud Rate of the SCI. 
  3.  * @param  port, port can be SCI0 / SCI1 
  4.  * @param  baudRate, the wanted baud rate. 
  5.  * @param  busClk, The SCI module clock. 
  6.  */  
  7. void SCISetBaudRate (unsigned char port, unsigned long baudRate, unsigned long busClk)  
  8. {  
  9.     unsigned short baudRateReg;  
  10.     baudRateReg = (unsigned short) (busClk / baudRate / 16);   
  11.     if (port == SCI0)  
  12.     {     
  13.        // Here we must write BDH first!   
  14.         SCI0BDH =  ( 0x1f & (baudRateReg >> 8) );  
  15.         SCI0BDL =  (0xff & baudRateReg);  
  16.     }  
  17.     else if(port == SCI1)  
  18.     {  
  19.         SCI1BDH =  ( 0x1f & (baudRateReg >> 8) );  
  20.         SCI1BDL =  (0xff & baudRateReg);  
  21.     }  
  22.     else  
  23.     {  
  24.         // Something must go wrong. Do nothing here!     
  25.     }  
  26. }  

设置奇偶校验位

 
  1. /** 
  2.  * Enable/Disable parity function and set the Parity type 
  3.  * @param port port can be SCI0 / SCI1 
  4.  * @param isEnable 0 for disable parity function, 1 for enable  
  5.  * @param type 0 for Even Parity, 1 for Odd Parity  
  6.  */  
  7. void SCISetParity (unsigned char port, unsigned char isEnable, unsigned char type)  
  8. {  
  9.     if (port == SCI0)  
  10.     {     
  11.         SCI0CR1_PE = (isEnable & 0x01);  
  12.         SCI0CR1_PT = (type & 0x01);  
  13.     }  
  14.     else if(port == SCI1)  
  15.     {  
  16.         SCI1CR1_PE = (isEnable & 0x01);   
  17.         SCI1CR1_PT = (type & 0x01);  
  18.     }  
  19.     else  
  20.     {  
  21.         // If code run here, something must go wrong. Do nothing here!     
  22.     }      
  23.       
  24. }  


使能数据位的长度

 
  1. /** 
  2.  * Set the Data Format Mode Bit  
  3.  * @param port port can be SCI0 / SCI1 
  4.  * @param bits must be 8 or 9 
  5.  */  
  6. void SCISetDataBit (unsigned char port, unsigned char bits)  
  7. {  
  8.     if (port == SCI0)  
  9.     {     
  10.         switch(bits)  
  11.         {  
  12.             case 8:  
  13.                 SCI0CR1_M = 0;   /* 1 start bit, 8 data bits, 1 stop bit */  
  14.                 break;  
  15.             case 9:  
  16.                 SCI0CR1_M = 1;   /* 1 start bit, 9 data bits, 1 stop bit */  
  17.                 break;  
  18.             default:  
  19.                 // If code run here, something must go wrong. Do nothing here!     
  20.                 break;  
  21.         }  
  22.     }  
  23.     else if(port == SCI1)  
  24.     {  
  25.         switch(bits)  
  26.         {  
  27.             case 8:  
  28.                 SCI1CR1_M = 0;   /* 1 start bit, 8 data bits, 1 stop bit */  
  29.                 break;  
  30.             case 9:  
  31.                 SCI1CR1_M = 1;   /* 1 start bit, 9 data bits, 1 stop bit */  
  32.                 break;  
  33.             default:  
  34.                 // If code run here, something must go wrong. Do nothing here!     
  35.                 break;  
  36.         }         
  37.     }  
  38.     else  
  39.     {  
  40.         // If code run here, something must go wrong. Do nothing here!     
  41.     }      
  42.       
  43. }  


设置串口的工作模式

NORMAL_MODE 是我们通常用的模式

LOOP_MODE 是自发自收模式

SING_WIRE_MODE 就是收发公用一条数据线的模式

 

  1. /** 
  2.  * Set the work mode of operation  
  3.  * @param port port can be SCI0 / SCI1 
  4.  * @param mode mode can be NORMAL_MODE / LOOP_MODE / SING_WIRE_MODE 
  5.  */  
  6. void SCISetWorkMode (unsigned char port, unsigned char mode)  
  7. {  
  8.     if (port == SCI0)  
  9.     {     
  10.         switch(mode)  
  11.         {  
  12.             case NORMAL_MODE:  
  13.                 SCI0CR1_LOOPS = 0;  
  14.                 SCI0CR1_RSRC = 0;  
  15.                 break;  
  16.             case LOOP_MODE:  
  17.                 SCI0CR1_LOOPS = 1;  
  18.                 SCI0CR1_RSRC = 0;  
  19.                 break;  
  20.             case SING_WIRE_MODE:  
  21.                 SCI0CR1_LOOPS = 1;  
  22.                 SCI0CR1_RSRC = 1;  
  23.                 break;  
  24.             default:  
  25.                 // If code run here, something must go wrong. Do nothing here!     
  26.                 break;  
  27.         }  
  28.     }  
  29.     else if(port == SCI1)  
  30.     {  
  31.         switch(mode)  
  32.         {  
  33.             case NORMAL_MODE:  
  34.                 SCI1CR1_LOOPS = 0;  
  35.                 SCI1CR1_RSRC = 0;  
  36.                 break;  
  37.             case LOOP_MODE:  
  38.                 SCI1CR1_LOOPS = 1;  
  39.                 SCI1CR1_RSRC = 0;  
  40.                 break;  
  41.             case SING_WIRE_MODE:  
  42.                 SCI1CR1_LOOPS = 1;  
  43.                 SCI1CR1_RSRC = 1;  
  44.                 break;  
  45.             default:  
  46.                 // If code run here, something must go wrong. Do nothing here!     
  47.                 break;  
  48.         }            
  49.     }  
  50.     else  
  51.     {  
  52.         // If code run here, something must go wrong. Do nothing here!     
  53.     }  
  54. }  

设置SCI模块是否在Wait 模式下工作

 
  1. /** 
  2.  * Enable/Disable the SCI in wait mode  
  3.  * @param port port can be SCI0 / SCI1 
  4.  * @param mode mode can be RUN_MODE / WAIT_MODE 
  5.  */  
  6. void SCISetPowerMode (unsigned char port, unsigned char mode)  
  7. {  
  8.     if (port == SCI0)  
  9.     {     
  10.         switch(mode)  
  11.         {  
  12.             case RUN_MODE:  
  13.                 SCI0CR1_SCISWAI = 0;  
  14.                 break;  
  15.             case WAIT_MODE:  
  16.                 SCI0CR1_SCISWAI = 1;  
  17.                 break;  
  18.             default:  
  19.                 // If code run here, something must go wrong. Do nothing here!     
  20.                 break;  
  21.         }  
  22.     }  
  23.     else if(port == SCI1)  
  24.     {  
  25.         switch(mode)  
  26.         {  
  27.             case RUN_MODE:  
  28.                 SCI1CR1_SCISWAI = 0;  
  29.                 break;  
  30.             case WAIT_MODE:  
  31.                 SCI1CR1_SCISWAI = 1;  
  32.                 break;  
  33.             default:  
  34.                 // If code run here, something must go wrong. Do nothing here!     
  35.                 break;  
  36.         }           
  37.     }  
  38.     else  
  39.     {  
  40.         // If code run here, something must go wrong. Do nothing here!     
  41.     }  
  42. }  

使能SCI模块的接收功能

 
  1. /** 
  2.  * Enable/Disable SCI Receiver 
  3.  * @param port  port can be SCI0 / SCI1 
  4.  * @param isEnable  0 disable 1 enable 
  5.  */  
  6. void SCIEnableRecv (unsigned char port, unsigned char isEnable)  
  7. {  
  8.     if (port == SCI0)  
  9.     {     
  10.         SCI0CR2_RE = (isEnable & 0x01);  
  11.     }  
  12.     else if(port == SCI1)  
  13.     {  
  14.         SCI1CR2_RE = (isEnable & 0x01);  
  15.     }  
  16.     else  
  17.     {  
  18.         // If code run here, something must go wrong. Do nothing here!     
  19.     }      
  20. }  

使能SCI模块的发送功能

 
  1. /** 
  2.  * Enable/Disable SCI Transmitter  
  3.  * @param port      port can be SCI0 / SCI1 
  4.  * @param isEnable  0 disable 1 enable 
  5.  */  
  6. void SCIEnableTrans (unsigned char port, unsigned char isEnable)  
  7. {  
  8.     if (port == SCI0)  
  9.     {     
  10.         SCI0CR2_TE = (isEnable & 0x01);  
  11.     }  
  12.     else if(port == SCI1)  
  13.     {  
  14.         SCI1CR2_TE = (isEnable & 0x01);  
  15.     }  
  16.     else  
  17.     {  
  18.         // If code run here, something must go wrong. Do nothing here!     
  19.     }      
  20. }  

发送数据

  1. /** 
  2.  * Send a char throungh SCI module. 
  3.  * @param port port can be SCI0 / SCI1 
  4.  * @param s the data to be sent 
  5.  */  
  6. void SCIPutChar ( unsigned char port, unsigned char s)  
  7. {    
  8.     if (port == SCI0)  
  9.     {     
  10.         while (SCI0SR1_TDRE == 0);   // SCI0SR1_TC 是发送完成  
  11.         SCI0DRL = s;  
  12.     }  
  13.     else  
  14.     {  
  15.         while (SCI1SR1_TDRE == 0);   // SCI1SR1_TC  
  16.         SCI1DRL = s;          
  17.     }  
  18. }  
  19.   
  20. /** 
  21.  * Send a char string throungh SCI module. 
  22.  * @param port  port can be SCI0 / SCI1 
  23.  * @param *str  the string to be sent 
  24.  */  
  25. void SCIPutStr (unsigned char port, unsigned char *str)  
  26. {  
  27.     while (0 != *str)  
  28.     {  
  29.         SCIPutChar(port, *str);  
  30.         str++;  
  31.     }  
  32. }  
  33.   
  34. /** 
  35.  * Send data throungh SCI module. 
  36.  * @param port  port can be SCI0 / SCI1 
  37.  * @param *p    pointer to the data to be sent 
  38.  * @param size  the size(byte) of the data 
  39.  */  
  40. void SCIWrite (unsigned char port, void *p, int size)  
  41. {  
  42.     unsigned char *str = (unsigned char *)p;  
  43.     while (size > 0)  
  44.     {  
  45.         SCIPutChar(port, *str);  
  46.         str++;  
  47.         size--;  
  48.     }  
  49. }  
  50.   
  51. /** 
  52.  * Send a short int value(Big Endian) throungh SCI module. 
  53.  * @param port  port can be SCI0 / SCI1 
  54.  * @param i     the data to be sent 
  55.  */  
  56. void SCIPutShortBigEndian (unsigned char port, short i)  
  57. {  
  58.     char * p = (char *)&i;  
  59.     SCIPutChar( port, p[0]);  
  60.     SCIPutChar( port, p[1]);  
  61. }  
  62.   
  63. /** 
  64.  * Send a short int value(Little Endian) throungh SCI module. 
  65.  * @param port  port can be SCI0 / SCI1 
  66.  * @param i     the data to be sent 
  67.  */  
  68. void SCIPutShortLittleEndian (unsigned char port, short i)  
  69. {  
  70.     char * p = (char *)&i;  
  71.     SCIPutChar( port, p[1]);  
  72.     SCIPutChar( port, p[0]);  
  73. }  
  74.   
  75. /** 
  76.  * Send a long int value(Big Endian) throungh SCI module. 
  77.  * @param port  port can be SCI0 / SCI1 
  78.  * @param i     the data to be sent 
  79.  */  
  80. void SCIPutLongBigEndian (unsigned char port, long i)  
  81. {  
  82.     char * p = (char *)&i;  
  83.     SCIPutChar( port, p[0]);  
  84.     SCIPutChar( port, p[1]);  
  85.     SCIPutChar( port, p[2]);  
  86.     SCIPutChar( port, p[3]);  
  87. }  
  88.   
  89. /** 
  90.  * Send a long int value(Little Endian) throungh SCI module. 
  91.  * @param port  port can be SCI0 / SCI1 
  92.  * @param i     the data to be sent 
  93.  */  
  94. void SCIPutLongLittleEndian (unsigned char port, long i)  
  95. {  
  96.     char * p = (char *)&i;  
  97.     SCIPutChar( port, p[3]);  
  98.     SCIPutChar( port, p[2]);  
  99.     SCIPutChar( port, p[1]);  
  100.     SCIPutChar( port, p[0]);  
  101. }  


接收数据

 
  1. /** 
  2.  * Receive a char data from SCI module,no reply. 
  3.  * @param  port port can be SCI0 / SCI1 
  4.  * @return the received char 
  5.  */  
  6. unsigned char SCIGetChar(unsigned char port)  
  7. {  
  8.     if (port == SCI0)  
  9.     {    
  10.         while( SCI0SR1_RDRF == 0);  
  11.         return SCI0DRL;  
  12.     }  
  13.     else  
  14.     {  
  15.         while( SCI1SR1_RDRF == 0);  
  16.         return SCI1DRL;  
  17.     }  
  18. }  

 

相应的头文件

 
  1. /** 
  2. * file sci.h 
  3. * author Li Yuan 
  4. * platform: mc9s12dp256B 
  5. * date: 2012-4-16 
  6. * version: 1.0.0 
  7. * description: SCI(Serial Communication Interface) Support Code 
  8. */  
  9.   
  10. #ifndef _SCI_H_  
  11. #define _SCI_H_  
  12.   
  13.   
  14.  #define SCI0               0  
  15.  #define SCI1               1  
  16.    
  17.  #define IDLE_LINE          0  
  18.  #define ADDRESS_MARK       1  
  19.    
  20.  #define NORMAL_MODE        0  
  21.  #define LOOP_MODE          1  
  22.  #define SING_WIRE_MODE     2  
  23.    
  24.  #define RUN_MODE           0  
  25.  #define WAIT_MODE          1  
  26.    
  27.  /* Function Declaration */  
  28.    
  29. /** 
  30.  * Set the Baud Rate of the SCI. 
  31.  * @param  port, port can be SCI0 / SCI1 
  32.  * @param  baudRate, the wanted baud rate. 
  33.  * @param  busClk, The SCI module clock. 
  34.  */  
  35. void SCISetBaudRate(unsigned char port, unsigned long baudRate, unsigned long busClk);  
  36.   
  37. /** 
  38.  * Set the Interrupt Enable Bit 
  39.  * @param  port  port can be SCI0 / SCI1 
  40.  * @param  tie   Transmitter Interrupt Enable BIt 
  41.  * @param  tcie  Transmission Complete Interrupt Enable BIt 
  42.  * @param  rie   Receiver Full Interrupt Enable BIt 
  43.  * @param  ilie  Idle Line Interrupt Enable BIt 
  44.  *                0 Interrupt requests Disabled  
  45.  *                1 Interrupt requests Enabled 
  46.  */  
  47. void SCISetIEBit(unsigned char port, unsigned char tie, unsigned char tcie, unsigned char rie, unsigned char ilie);  
  48.   
  49. /** 
  50.  * Enable The Tx interrupt  (Transmitter Interrupt Enable BIt) 
  51.  * @param  port, port can be SCI0 / SCI1 
  52.  */  
  53. void SCIEnableTxInt(unsigned char port);  
  54.   
  55. /** 
  56.  * Disable The Tx interrupt  (Transmitter Interrupt Enable BIt) 
  57.  * @param  port, port can be SCI0 / SCI1 
  58.  */  
  59. void SCIDisTxInt(unsigned char port);  
  60.   
  61. /** 
  62.  * Enable/Disable SCI Receiver 
  63.  * @param port  port can be SCI0 / SCI1 
  64.  * @param isEnable  0 disable 1 enable 
  65.  */  
  66. void SCIEnableRecv(unsigned char port, unsigned char isEnable);  
  67.   
  68. /** 
  69.  * Enable/Disable SCI Transmitter  
  70.  * @param port      port can be SCI0 / SCI1 
  71.  * @param isEnable  0 disable 1 enable 
  72.  */  
  73. void SCIEnableTrans(unsigned char port, unsigned char isEnable);  
  74.   
  75. /** 
  76.  * Set the Idle Line Type 
  77.  * @param port  port can be SCI0 / SCI1 
  78.  * @param type  0 Idle char bit count begins after start bit 
  79.  *              1 Idle char bit count begins after stop bit 
  80.  */  
  81. void SCISetIdleLineType(unsigned char port, unsigned char type);  
  82.   
  83. /** 
  84.  * Set the Wakeup Condition. 
  85.  * @param port      port can be SCI0 / SCI1 
  86.  * @param condi     0 for Idle line wakeup, 1 for address mark wakeup  
  87.  */  
  88. void SCISetWakeupCondi(unsigned char port, unsigned char condi);  
  89.   
  90. /** 
  91.  * Enable/Disable parity function and set the Parity type 
  92.  * @param port port can be SCI0 / SCI1 
  93.  * @param isEnable 0 for disable parity function, 1 for enable  
  94.  * @param type 0 for Even Parity, 1 for Odd Parity  
  95.  */  
  96. void SCISetParity(unsigned char port, unsigned char isEnable, unsigned char type);  
  97.   
  98. /** 
  99.  * Set the Data Format Mode Bit  
  100.  * @param port port can be SCI0 / SCI1 
  101.  * @param bits must be 8 or 9 
  102.  */  
  103. void SCISetDataBit(unsigned char port, unsigned char bits);  
  104.   
  105. /** 
  106.  * Set the work mode of operation  
  107.  * @param port port can be SCI0 / SCI1 
  108.  * @param mode mode can be NORMAL_MODE / LOOP_MODE / SING_WIRE_MODE 
  109.  */  
  110. void SCISetWorkMode(unsigned char port, unsigned char mode);  
  111.   
  112. /** 
  113.  * Enable/Disable the SCI in wait mode   
  114.  * @param port port can be SCI0 / SCI1 
  115.  * @param mode mode can be RUN_MODE / WAIT_MODE 
  116.  */  
  117. void SCISetPowerMode(unsigned char port, unsigned char mode);  
  118.   
  119. /** 
  120.  * Set the TXDIR ( Only for Single Wire MODE) 
  121.  * @param port port can be SCI0 / SCI1 
  122.  * @param dir 0 TXD used as input, 1 TXD used as output 
  123.  */  
  124. void SCISetTXDIR(unsigned char port, unsigned char dir);  
  125.   
  126. /** 
  127.  * Send a char throungh SCI module. 
  128.  * @param port port can be SCI0 / SCI1 
  129.  * @param s the data to be sent 
  130.  */  
  131. void SCIPutChar( unsigned char port, unsigned char s);  
  132.   
  133. /** 
  134.  * Receive a char data from SCI module,no reply. 
  135.  * @param  port port can be SCI0 / SCI1 
  136.  * @return the received char 
  137.  */  
  138. unsigned char SCIGetChar(unsigned char port);  
  139.   
  140. /** 
  141.  * Send a short int value(Big Endian) throungh SCI module. 
  142.  * @param port  port can be SCI0 / SCI1 
  143.  * @param i     the data to be sent 
  144.  */  
  145. void SCIPutShortBigEndian (unsigned char port, short i);  
  146.   
  147. /** 
  148.  * Send a short int value(Little Endian) throungh SCI module. 
  149.  * @param port  port can be SCI0 / SCI1 
  150.  * @param i     the data to be sent 
  151.  */  
  152. void SCIPutShortLittleEndian (unsigned char port, short i);  
  153.   
  154. /** 
  155.  * Send a long int value(Big Endian) throungh SCI module. 
  156.  * @param port  port can be SCI0 / SCI1 
  157.  * @param i     the data to be sent 
  158.  */  
  159. void SCIPutLongBigEndian (unsigned char port, long i);  
  160.   
  161. /** 
  162.  * Send a long int value(Little Endian) throungh SCI module. 
  163.  * @param port  port can be SCI0 / SCI1 
  164.  * @param i     the data to be sent 
  165.  */  
  166. void SCIPutLongLittleEndian (unsigned char port, long i);  
  167.   
  168. /** 
  169.  * Send a char string throungh SCI module. 
  170.  * @param port  port can be SCI0 / SCI1 
  171.  * @param *str  the string to be sent 
  172.  */  
  173. void SCIPutStr(unsigned char port, unsigned char *str);  
  174.   
  175.   
  176. /** 
  177.  * Send data throungh SCI module. 
  178.  * @param port  port can be SCI0 / SCI1 
  179.  * @param *p    pointer to the data to be sent 
  180.  * @param size  the size(byte) of the data 
  181.  */  
  182. void SCIWrite(unsigned char port, void *p, int size);  
  183.   
  184. #endif  

 

下面给个简单的例子

 
  1. #include       /* common defines and macros */  
  2. #include "derivative.h"      /* derivative-specific definitions */  
  3. #include  "sci.h"  
  4.   
  5. void main(void)   
  6. {  
  7.     char C;  
  8.     EnableInterrupts;  
  9.       
  10.     SCISetWorkMode(SCI0, NORMAL_MODE);  
  11. SCISetPowerMode(SCI0, RUN_MODE);  
  12.     SCISetBaudRate(SCI0, 9600, 16384000L); // 16M Clock  
  13.     SCISetDataBit(SCI0, 8);  
  14.     SCISetParity(SCI0, 0, 0);  
  15.     SCIEnableRecv(SCI0, 1);  
  16.     SCIEnableTrans(SCI0, 1);     
  17.       
  18.     for(;;)   
  19.     {  
  20.         _FEED_COP(); /* feeds the dog */  
  21.         C = SCIGetChar(SCI0);  
  22.         SCIPutChar(SCI0, C);  
  23.     } /* loop forever */  
  24.       
  25.     /* please make sure that you never leave main */  
  26. }  


 

先写这么多,剩下的明天继续。下一篇笔记中将给出如何利用串口的收发中断和环形缓冲区来实现较为完善的串口驱动。

 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
教你如何选一款内外兼备的吊顶LED灯