串行接口分为异步串行接口和同步串行接口两种。异步串行接口统称为通用异步收发器(UART)接口,同步串行接口有SPI和I2C等,同步串行接口除了包含数据线(SPI有两根单向数据线MISO和MOSI,I2C有一根双向数据线SDA)外,还包含时钟线(SPI和I2C的时钟线分别是SCK和SCL)。
SPI和I2C都可以连接多个从设备,但两者选择从设备的方法不同:SPI通过硬件(NSS引脚)实现,而I2C通过软件(地址)实现。
为了使不同电压输出的器件能够互连,I2C的数据线SDA和时钟线SCL开漏输出,使用时必须通过电阻连接到电源线。
同步串行接口可以用专用接口电路硬件实现,也可以用通用并行接口软件实现。
UART的相关标准规定了接口的机械特性、电气特性和功能特性等,UART的电气特性标准包括RS-232C、RS-422、RS-423和RS-485等,其中RS-232C是最常用串行通信标准。
RS-232C是数据终端设备(DTE)和数据通信设备(DCE)之间串行二进制数据交换接口技术标准,其中DTE包括微机、微控制器和打印机等,DCE包括调制解调器MODEM、GSM模块和Wi-Fi模块等。
RS-232C机械特性规定RS-232C使用25针D型连接器,后来简化为9针D型连接器。
RS-232C电气特性采用负逻辑:逻辑“1”的电平低于-3 V,逻辑“0”的电平高于+3 V,这和 TTL 的正逻辑(逻辑“1”为高电平,逻辑“0”为低电平)不同,因此通过 RS-232C和TTL器件通信时必须进行电平转换。
目前微控制器的UART接口采用的是TTL正逻辑,和TTL器件连接不需要电平转换。和采用负逻辑的计算机相连时需要进行电平转换,或使用UART-USB转换器连接。
RS-232C功能特性规定各引脚的功能,9针D型连接器的引脚功能如表3.2所示,其中最常用的引脚只有3个:RXD(接收数据)、TXD(发送数据)和GND(地)。
表3.2 RS-232C引脚功能
从表3.2中可以看出,用RS-232C连接DTE和DCE时各引脚直接连接,DTE的TXD(输出)直接连接DCE的TXD(输入),DTE的RXD(输入)直接连接DCE的RXD(输出)。
如果用RS-232C连接DTE和DTE(如微机和微控制器),相关引脚必须交叉连接,DTE1的TXD(输出)连接DTE2的RXD(输入),DTE1的RXD(输入)连接DTE2的TXD(输出)。
RS-232C的主要指标有2个:数据速率和数据格式。数据速率用波特率表示,数据格式包括1个起始位、5~8个数据位、0~1个校验位和1~2个停止位,如图3.18所示。
图3.18 RS-232C数据格式
通信双方的数据速率和数据格式必须一致,否则无法实现通信。
CC3200包含两个可编程UART接口(UARTA0~1,具体引脚分配参见表D.2),CC3200 UART具有下列特性。
● 可编程波特率发生器,允许速度高达3 Mbps。
● 独立的16×8发送(TX)和接收(RX)FIFO,减轻CPU中断处理负载。
● 可编程FIFO长度,包括提供传统双缓冲接口的单字节操作。
● FIFO触发阈值包括1/8、1/4、1/2、3/4和7/8。
● 标准的异步通信起始、停止和奇偶校验位。
● 可编程串行接口特性。
✧ 5、6、7或8位数据。
✧ 偶、奇或无校验生成/检测。
✧ 1或2个停止位生成。
● 支持RTS和CTS调制解调器握手。
● 标准的FIFO阈值中断和传输结束中断。
● 使用DMA可实现高效传输。
✧ 单独的发送和接收通道。
✧ FIFO中有数据的单个请求接收和可编程FIFO阈值的突发请求接收。
✧ FIFO中有空间的单个请求发送和可编程FIFO阈值的突发请求发送。
UART示例程序在example\uart_demo目录中,Uart_demo项目CC3200 LaunchPad电路如图3.19所示。
图3.19 Uart_demo项目CC3200 LaunchPad电路图
CC3200 UARTA0(TX-PIN_55/RX-PIN_57)经过电平转换电路74LVC1T45(可以省略)和UART-USB转换电路FT2232D转换后,通过USB接口与PC相连。
(1)将CC3200 LaunchPad通过USB线与PC连接。
(2)在PC上打开超级终端Tera Term。
(3)参考2.1.2节中的“CCS使用”,将uart_demo项目导入CCS,在“Project Explorer”(项目浏览器)视图中可以看出uart_demo项目包含下列4个程序文件。
● main.c:主程序文件。
● pinmux.c:PinMux应用程序生成的UART引脚配置程序文件。
● uart_if.c:UART接口驱动程序文件。
● startup_ccs.c:CCS启动程序文件。
Uart_demo项目程序流程图如图3.20所示。
图3.20 Uart_demo项目程序流程图
(4)在CCS中右击“Project Explorer”(项目浏览器)中的uart_demo项目,在弹出菜单中单击“Properties”(属性),打开“属性”对话框,确认“Device”(器件)选择CC3200,选择“Compiler version”(编译器版本)为TI v5.2.2,如图2.17所示。
(5)在CCS中单击“Run”(运行)→“Debug”(调试)或按“F11”键,CCS首先生成目标文件uart_demo.out,然后将目标文件uart_demo.out下载到CC3200并进入调试界面。
(6)单击“Run”(运行)→“Resume”(运行)或单击调试工具栏中的“Resume”(运行)按钮
或按“F8”键,运行程序,在超级终端窗口将出现图3.21所示的程序标题和用法信息及命令提示符。
图3.21 Uart_demo项目超级终端信息
(7)在超级终端中输入字母数字字符,输入的内容回显在超级终端中,按Enter(回车)键,将回显字符串。如果字符串长度达到80个字符,将自动回显字符串,不等待按Enter(回车)键。
(8)单击调试工具栏中的“Suspend”(暂停)按钮
暂停程序的运行。
(9)单击调试工具栏中的“Restart”(重新开始)按钮
,程序停在main()函数开始处。注意:在程序的分析过程中,可随时单击“Restart”(重新开始)按钮
复位程序。
下面详细介绍程序的分析步骤,主要包括下列内容。
● 初始化开发板:BoardInit()。
● 引脚复用配置:PinMuxConfig()。
● 终端操作。
初始化开发板包括设置中断向量表、允许处理器中断、允许SysTick中断和初始化MCU等步骤,调用了相应的中断API函数,具体内容和Blinky项目相同。
引脚复用配置程序由PinMux应用程序根据设计需要自动生成,程序代码在pinmux.c中,其中调用了相应的PRCM和PIN API函数。
右击main()中PinMuxConfig()语句,在弹出菜单中单击“Run to Line”(允许到行),运行到PinMuxConfig()语句。
单击调试工具栏中的“Step Into”(单步进入)按钮
,进入 PinMuxConfig()函数,如图3.22所示。
图3.22 Uart_demo项目PinMuxConfig()函数
UART引脚复用配置包括下列内容。
● 允许UART时钟:PRCMPeripheralClkEnable()。
● 配置UART引脚:PinTypeUART()。
(1)允许UART时钟PRCMPeripheralClkEnable()。
功能:允许外设时钟。
参数说明:
● ulPeripheral:外设号,UARTA0的外设号是0x0C,在prcm.h中定义。
● ulClkFlags:时钟标志,设置值是PRCM_RUN_MODE_CLK(运行模式时钟)。
PRCMPeripheralClkEnable()的声明在prcm.h中,代码在prcm.c中。
注意:GPIO和UART等外设接口和外设都使用PRCMPeripheralClkEnable()函数允许外设时钟,不同之处是参数ulPeripheral(外设号)不同。
单击调试工具栏中的“Step Over”(单步跨越)按钮
两次,运行 PRCMPeripheralClk Enable()语句。
(2)配置UART引脚PinTypeUART()。
① 单击调试工具栏中的“Step Into”(单步进入)按钮
,进入 PinTypeUART()函数,如图3.23所示。
图3.23 Uart_demo项目PinTypeUART()函数
功能:配置UART引脚。
参数说明:
● ulPin:引脚号,UARTA0_TX和UARTA0_RX的引脚号分别是PIN_55和PIN_57。
● ulPinMode:引脚模式,PIN_55和PIN_57的PIN_MODE_3为UART模式。
PinTypeUART()的声明在pin.h中,代码在pin.c中。PinTypeUART()通过调用PinModeSet()和PinConfigSet()实现UART引脚的配置。
注意:配置GPIO引脚PinTypeGPIO()和配置UART引脚PinTypeUART()都通过调用PinModeSet()和PinConfigSet()实现,两者的不同之处是PinModeSet()的参数ulPinMode(引脚模式)不同,前者为GPIO模式,后者为UART模式。
② 单击调试工具栏中的“Step Return”(单步返回)按钮
,运行上述函数,然后退出函数,返回PinMuxConfig()函数的第二条PinTypeUART()语句。
③ 单击调试工具栏中的“Step Return”(单步返回)按钮
,对PIN_57进行配置,然后退出函数,返回main()函数的InitTerm()语句。
终端操作主要包括下列内容。
● 初始化终端:InitTerm()(UARTConfigSetExpClk())。
● 清除终端:ClearTerm()(UARTCharPut())。
● 显示标题:DisplayBanner()。
● 显示用法(显示字符串):Message()。
主要程序代码在uart_if.c中,其中调用了相应的UART API函数,主要是UARTConfig SetExpClk()、UARTCharPut()和UARTCharGet()。
(1)初始化终端InitTerm()。
① 单击调试工具栏中的“Step Into”(单步进入)按钮
,进入InitTerm()函数,如图3.24所示。
图3.24 Uart_demo项目InitTerm()函数
初始化终端InitTerm()通过调用UARTConfigSetExpClk()实现,UARTConfigSetExpClk()又通过调用PRCMPeripheralClkGet()获得UART时钟。
② 单击调试工具栏中的“Step Into”(单步进入)按钮
两次,进入 PRCMPeripheral ClkGet()。
功能:获取外设时钟。
参数说明:ulPeripheral,外设号,UARTA0的外设号是0x0C,在prcm.h中定义。
返回值:外设时钟,UARTA0的外设时钟是系统时钟SYS_CLK(80 MHz)。
PRCMPeripheralClkGet()的声明在prcm.h中,代码在prcm.c中。
③ 单击调试工具栏中的“Step Return”(单步返回)按钮
,运行上述函数,然后退出函数,返回InitTerm()函数的UARTConfigSetExpClk()语句。
④ 单击调试工具栏中的“Step Into”(单步进入)按钮
,进入UARTConfigSetExpClk()函数,如图3.25所示。
功能:配置UART接口。
参数说明:
图3.25 Uart_demo项目UARTConfigSetExpClk()函数(部分)
● ulBase:UART端口基地址,UARTA0的端口基地址为0x4000 C000,在hw_memmap.h中定义。
● ulUARTClk:UART时钟(80 MHz),通过调用PRCMPeripheralClkGet()获得。
● ulBaud:UART波特率,设置值为115 200。
● ulConfig:UART参数,包括数据位数(5~8位)、停止位数(1~2位)和校验位(偶校验、奇校验和无校验)等下列值。
✧ UART_CONFIG_WLEN_8:8位数据,0x0000 0060。
✧ UART_CONFIG_WLEN_7:7位数据,0x0000 0040。
✧ UART_CONFIG_WLEN_6:6位数据,0x0000 0020。
✧ UART_CONFIG_WLEN_5:5位数据,0x0000 0000。
✧ UART_CONFIG_STOP_TWO:2个停止位,0x0000 0008。
✧ UART_CONFIG_STOP_ONE:1个停止位,0x0000 0000。
✧ UART_CONFIG_PAR_EVEN:偶校验,0x0000 0006。
✧ UART_CONFIG_PAR_ODD:奇校验,0x0000 0002。
✧ UART_CONFIG_PAR_NONE:无校验,0x0000 0000。
设置值是0x60:UART_CONFIG_WLEN_8(8位数据)、UART_CONFIG_STOP_ONE (1个停止位)和UART_CONFIG_PAR_NONE(无校验),参见图3.24。
UARTConfigSetExpClk()的声明在uart.h中,代码在uart.c中。
在通过UARTConfigSetExpClk()配置UART接口前,需要禁止UART,配置UART接口后,再允许UART。
功能:禁止UART。
参数说明:ulBase,UART端口基地址,UARTA0的端口基地址为0x4000 C000。
UARTDisable()的声明在uart.h中,代码在uart.c中。
功能:允许UART。
参数说明:ulBase,UART端口基地址,UARTA0的端口基地址为0x4000 C000。
UARTEnable()的声明在uart.h中,代码在uart.c中。
⑤ 单击调试工具栏中的“Step Return”(单步返回)按钮
,运行UARTConfigSetExpClk()函数,然后退出函数,返回InitTerm()函数。
⑥ 单击调试工具栏中的“Step Return”(单步返回)按钮
,退出InitTerm()函数,返回main()函数的ClearTerm()语句。
(2)清除终端ClearTerm()。
清除终端通过调用Message("\33[2J\r")实现,Message()又循环调用UARTCharPut()显示字符串。
① 单击调试工具栏中的“Step Into”(单步进入)按钮
,进入ClearTerm()函数。
② 再单击调试工具栏中的“Step Into”(单步进入)按钮
两次,进入Message()函数,如图3.26所示。
图3.26 Uart_demo项目Message()函数
③ 单击调试工具栏中的“Step Into”(单步进入)按钮
4次,进入UARTCharPut()函数,如图3.27所示。
图3.27 Uart_demo项目UARTCharPut()函数
功能:UART发送字符。
参数说明:
● ulBase:UART端口基地址,UARTA0的端口基地址为0x4000 C000。
● ucData:发送数据。
UARTCharPut()的声明在uart.h中,代码在uart.c中。
④ 单击调试工具栏中的“Step Return”(单步返回)按钮
3 次,运行 UARTCharPut()函数,然后依次退出 UARTCharPut()、Message()和 ClearTerm()函数,返回 main()函数的DisplayBanner()语句,超级终端中的内容被清除。
(3)显示标题DisplayBanner()。
单击调试工具栏中的“Step Over”(单步跨越)按钮
,运行显示标题 DisplayBanner()函数,DisplayBanner()通过调用Report()在超级终端中显示下列标题。
Report()是格式字符串显示函数,通过调用系统函数vsnprintf()实现格式字符串的转换,再调用Message()实现格式字符串的显示,功能和printf()类似。
(4)显示用法Message()。
右击while(1)中的“cCharacter=UartGetChar()”语句,在弹出菜单中单击“Run to Line”(运行到行),运行到“cCharacter=UartGetChar()”语句,超级终端中显示下列程序用法信息和命令提示符“cmd#”。
(5)UART接收字符UARTCharGet()。
① 单击调试工具栏中的“Step Into”(单步进入)按钮
,进入UARTCharGet()函数,如图3.28所示。
图3.28 Uart_demo项目UARTCharGet()函数
功能:UART接收字符。
参数说明:ulBase,UART端口基地址,UARTA0的端口基地址为0x4000 C000。
返回值:接收数据。
UARTCharGet()的声明在uart.h中,代码在uart.c中。
注意:main.c中使用了下列宏定义。
② 单击调试工具栏中的“Step Return”(单步返回)按钮
,运行UARTCharGet()函数,在超级终端中输入任一字符(如“1”),退出 UARTCharGet()函数,返回到 main()函数中的“cCharacter=UartGetChar()”语句。
③ 单击调试工具栏中的“Step Over”(单步跨越)按钮
,运行赋值语句cCharacter=UartGetChar()。
图3.29 表达式窗口
④ 将鼠标移到main.c中的“cCharacter”处,弹出“Expression”(表达式)窗口,如图3.29所示。
⑤ 单击“cCharacter”右边“Value”下边的数值“1”,输入“2”、“0x32”或“50”,然后按“Enter”(回车)键,cCharacter的值变为2。
(6)回显接收字符UARTCharPut()。
单个字符的回显通过调用UartPutChar()即UARTCharPut()实现,按Enter(回车)键或字符串长度达到80个字符时通过调用Report()实现字符串回显。
① 单击调试工具栏中的“Step Over”(单步跨越)按钮
3次,运行UartPutChar()语句发送字符,在超级终端的命令提示符后显示“2”。
② 双击“cCharacter=UartGetChar()”语句行号左侧的断点标志清除断点。③ 在“Report("\n\rcmd#%s\n\rcmd#",cString)”语句处设置断点。
④ 单击调试工具栏中的“Resume”(运行)按钮
,运行程序。
⑤ 在超级终端中输入字母数字字符,输入的字符回显在超级终端中。
⑥ 在超级终端中按“Enter”(回车键)或输入字符达到80个时,程序停在断点处。
⑦ 单击调试工具栏中的“Step Over”(单步跨越)按钮
,运行Report()语句发送字符串,输入的字符串回显在超级终端中。
⑧ 双击“Report("\n\rcmd#%s\n\rcmd#",cString)”语句行号左侧的断点标志清除断点。
⑨ 单击调试工具栏中的“Terminate”(结束)按钮
,结束调试返回编辑界面。
综上所述,Uart_demo项目使用的与UART有关的API函数如表3.3所示。
表3.3 Uart_demo项目使用的与UART有关的API函数
UART的使用主要包括引脚复用配置、初始化终端和UART数据操作等。
引脚复用配置包括允许UART时钟PRCMPeripheralClkEnable()和配置UART引脚Pin TypeUART(),API声明如下。
初始化终端主要是配置UART接口UARTConfigSetExpClk(),用于配置UART波特率和数据格式(包括数据位数、停止位数和校验位等),其中包含允许UART UARTEnable()和禁止UART UARTDisable(),API声明如下。
UARTConfigSetExpClk()的ulConfig参数包括数据位数(5~8位)、停止位数(1~2位)和校验位(偶校验、奇校验和无校验)等下列值。
● UART_CONFIG_WLEN_8:8位数据,0x0000 0060。
● UART_CONFIG_WLEN_7:7位数据,0x0000 0040。
● UART_CONFIG_WLEN_6:6位数据,0x0000 0020。
● UART_CONFIG_WLEN_5:5位数据,0x0000 0000。
● UART_CONFIG_STOP_TWO:2个停止位,0x0000 0008。
● UART_CONFIG_STOP_ONE:1个停止位,0x0000 0000。
● UART_CONFIG_PAR_EVEN:偶校验,0x0000 0006。
● UART_CONFIG_PAR_ODD:奇校验,0x0000 0002。
● UART_CONFIG_PAR_NONE:无校验,0x0000 0000。
UART数据操作分别使用UART发送字符UARTCharPut()和UART接收字符UART CharGet()实现,API声明如下。
UART示例程序主程序的while(1)循环中“发送并保存字符”处理出现了两次,可以将其合并,同时可将接收和发送字符宏定义UartGetChar()和UartPutChar()改用UART API函数UARTCharGet()和UARTCharPut(),改进后的程序如下。