串行接口分为异步接口和同步接口两种。异步串行接口统称为通用异步收发器(UART)接口,同步串行接口有SPI和I2C等,同步串行接口包含数据线和时钟线,主设备和从设备的时钟必须保持一致,而异步通信的主设备和从设备的时钟不一定要一致。
- SPI有两根单向数据线MISO和MOSI,时钟线SCK;
- I2C有一根双向数据线SDA,时钟线SCL;
- SPI和I2C都可以连接多个从设备,但SPI通过硬件实现选择,I2C通过软件实现选择;
RS-233C是UART最常用串行通信标准,采用的是TTL正逻辑,和TTL器件连接不需要电平转换。和采用负逻辑的计算机相连需要UART-USB转换器进行电平转换。从以下CC3200的功能框图可以看出CC3200 launch开发板是自带型号为FT2232的USB-UART转换器的,不需要我们另外加。
CC3200包含两个可编程的UART接口,UARTA0和UARTA1,实物图如下图。
上图是CC3200 LaunchPad电路图,URATA0的TX口和RX口经过电平转换电路74LVC1T45和UART-USB转换电路FT2232D转换后,通过USB接口与PC相连。
- UART示例程序在SDK的examples文件当中的Uart_demo工程,参照
文章导入CCS。
- main.c:主程序文件。
- pinmux.c:引脚配置文件。
- uart_if.c:UART接口驱动程序文件。
- startup_css.c:CCS启动程序文件。
项目程序流程图如下图。
- 进入Debug调试界面,点击运行,并且打开Tera Term软件,选择CC3200对应的端口。
Tera Term是来自国外的一款界面简洁,功能实用的串口调试工具。它是Microsoft Windows的终端仿真器,支持串行端口,远程登录和SSH连接,内置的宏脚本语言。Tera Term通常用于自动执行与从PC发起的远程连接相关的任务。
具体下载流程可参考链接: teraterm–一款超好用堪比MobaXterm的远程终端连接软件,能解决shell端tab键等自动补全命令功能的缺失问题.
最终显示结果如下图。
主函数
void main()
{
char cString[MAX_STRING_LENGTH+1];
char cCharacter;
int iStringLength = 0;
//
// Initailizing the board
//
BoardInit();
//
// Muxing for Enabling UART_TX and UART_RX.
//
PinMuxConfig();
//
// Initialising the Terminal.
//
InitTerm();
//
// Clearing the Terminal.
//
ClearTerm();
DisplayBanner(APP_NAME);
Message("\t\t****************************************************\n\r");
Message("\t\t\t CC3200 UART Echo Usage \n\r");
Message("\t\t Type in a string of alphanumeric characters and \n\r");
Message("\t\t pressenter, the string will be echoed. \n\r") ;
Message("\t\t Note: if string length reaches 80 character it will \n\r");
Message("\t\t echo the string without waiting for enter command \n\r");
Message("\t\t ****************************************************\n\r");
Message("\n\n\n\r");
Message("cmd#");
while(1)
{
//
// Fetching the input from the terminal.
//
cCharacter = UartGetChar();
g_iCounter++;
if(cCharacter == '\r' || cCharacter == '\n' ||
(iStringLength >= MAX_STRING_LENGTH -1))
{
if(iStringLength >= MAX_STRING_LENGTH - 1)
{
UartPutChar(cCharacter);
cString[iStringLength] = cCharacter;
iStringLength++;
}
cString[iStringLength] = '\0';
iStringLength = 0;
//
// Echoes the input string
//
Report("\n\rcmd#%s\n\rcmd#", cString);
}
else
{
UartPutChar(cCharacter);
cString[iStringLength] = cCharacter;
iStringLength++;
}
}
}
工程函数解析
- 函数引用关系整理
绿色框图代表的是SDK工具包提供的库函数,这是已经封装好的函数,只要导入头文件和相关驱动文件就可以直接引用。蓝色函数是新定义的函数,从图中可以很明显看出,整个工程也就三个新定义的函数,一个是主函数,一个是DisBanner函数,一个是引脚复用配置函数(可用PinMux软件直接生成)。所以大家一定要熟练引用库函数,不要走了冤枉路,这样可以节省大量开发的时间。
- 初始化开发板BoardInit()
具体内容和Bliny项目相同,在此不多赘述。 - 引脚复用配置PinMuxConfig()
引脚复用配置函数可以由PinMux软件直接生成。 - 终端操作
- 初始化终端
- 清除终端
- 显示标题
- 显示字符串
(1)初始化终端函数(API函数)
void InitTerm()//初始化终端函数
{
#ifndef NOTERM
MAP_UARTConfigSetExpClk(CONSOLE,MAP_PRCMPeripheralClockGet(CONSOLE_PERIPH),
UART_BAUD_RATE, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
UART_CONFIG_PAR_NONE));
#endif
__Errorlog = 0;
}
//MAP_PRCMPeripheralClockGet函数获取外设时钟
//MAP_UARTConfigSetExpClk函数配置UART接口
(2)清除终端函数(API函数)
void
ClearTerm()//清除终端函数
{
Message("\33[2J\r");
}
void
Message(const char *str)
{
#ifndef NOTERM
if(str != NULL)
{
while(*str!='\0')
{
MAP_UARTCharPut(CONSOLE,*str++);
}
}
#endif
}
(3)显示标题函数
这个函数其实就是连续输出5行文本,用作标题,其实直接写在主函数也行。
转义字符 | 意义 |
---|---|
\t | 水平制表(HT) (跳到下一个TAB位置) |
\n | 换行(LF) ,将当前位置移到下一行开头 |
\r | 回车(CR) ,将当前位置移到本行开头 |
static void
DisplayBanner(char * AppName)//显示标题函数
{
Report("\n\n\n\r");
Report("\t\t *************************************************\n\r");
Report("\t\t CC3200 %s Application \n\r", AppName);
Report("\t\t *************************************************\n\r");
Report("\n\n\n\r");
}
(4)显示格式字符串/普通字符串函数(API函数)
笔者看来,格式字符串就是带着%s、%f等具备可变的字符变量的字符串,比如“x=%f”,这个%f是还未确定的,需要求出变量的。
而普通字符串就是固定的文本,不会存在变量,比如“hello!word”。这就是两者函数的区别。这两个函数都是库函数,在引用的时候注意有所区别就好。
void
Message(const char *str) //显示普通字符串函数
{
#ifndef NOTERM
if(str != NULL)
{
while(*str!='\0')
{
MAP_UARTCharPut(CONSOLE,*str++);
}
}
#endif
}
int Report(const char *pcFormat, ...)//显示格式字符串函数
{
int iRet = 0;
#ifndef NOTERM
char *pcBuff, *pcTemp;
int iSize = 256;
va_list list;
pcBuff = (char*)malloc(iSize);
if(pcBuff == NULL)
{
return -1;
}
while(1)
{
va_start(list,pcFormat);
iRet = vsnprintf(pcBuff,iSize,pcFormat,list);
va_end(list);
if(iRet > -1 && iRet < iSize)
{
break;
}
else
{
iSize*=2;
if((pcTemp=realloc(pcBuff,iSize))==NULL)
{
Message("Could not reallocate memory\n\r");
iRet = -1;
break;
}
else
{
pcBuff=pcTemp;
}
}
}
Message(pcBuff);
free(pcBuff);
#endif
return iRet;
}
(5)UART接收字符函数(API函数)
long
UARTCharGet(unsigned long ulBase)//UART接收字符函数
{
//
// Check the arguments.
//
ASSERT(UARTBaseValid(ulBase));
//
// Wait until a char is available.
//
while(HWREG(ulBase + UART_O_FR) & UART_FR_RXFE)
{
}
//
// Now get the char.
//
return(HWREG(ulBase + UART_O_DR));
}
(6)UART发送字符函数(API函数)
void
UARTCharPut(unsigned long ulBase, unsigned char ucData)//UART发送字符
{
//
// Check the arguments.
//
ASSERT(UARTBaseValid(ulBase));
//
// Wait until space is available.
//
while(HWREG(ulBase + UART_O_FR) & UART_FR_TXFF)
{
}
//
// Send the char.
//
HWREG(ulBase + UART_O_DR) = ucData;
}
参考文献:《ARM Cortex-M4+Wi-Fi MCU应用指南-CC3200 CCS基础篇》郭书军编著 电子工业出版社