因为想申请 CSDN 博客认证需要一定的粉丝量,而我写了五年博客才 700 多粉丝,本文开启关注才可阅读全文,很抱歉影响您的阅读体验

  • 为了准备电赛临时学一下TM4C123G,简单记录学习内容
  • 大家可以在这里下载我收集的资源,非常全面,花了很大功夫收集来的,还有书籍、例程代码等
  • 还可以在TI官网下载相关文档TI官网

文章目录

  • 一、实验简介
  • 二、TM4C的UART资源
    • (1)Tiva控制器的UART特征
    • (2)UART结构图
    • (3)UART和引脚的复用映射表
    • (4)FIFO操作
    • (5)中断、
  • 三、编程实践
    • (1)UART配置和使用的基本流程
    • (2)使用类似C语言中stdio.h的方法
    • (3)UART中断
    • (4)FIFO测试
  • 四、部分库函数小结
    • (1)void UARTprintf(const char *pcString, ...)
    • (2)void UARTCharPut(uint32_t ui32Base, unsigned char ucData)
    • (3)int32_t UARTCharGet(uint32_t ui32Base)
    • (4)bool UARTCharPutNonBlocking(uint32_t ui32Base, unsigned char ucData)
    • (5)int32_t UARTCharGetNonBlocking(uint32_t ui32Base)
    • (6)void UARTFIFOLevelSet(uint32_t ui32Base, uint32_t ui32TxLevel,uint32_t ui32RxLevel)
    • (7)void UARTFIFOEnable(uint32_t ui32Base)

一、实验简介

通过TM4C123G的板载UART串口和电脑通信,观察各种中断发生情况

二、TM4C的UART资源

简单介绍TM4C123G的UART资源,关于波特率发生原理、数据传输流程、ISR、调制解调器握手、9位UART模式、环回模式、DMA等内容省略

(1)Tiva控制器的UART特征

(2)UART结构图

(3)UART和引脚的复用映射表

这个表非常重要,编程时要根据这个参考

(4)FIFO操作

关于FIFO的作用可以看看这篇文章,讲的很明白:uart FIFO

  • 每个UART有两个16x8的缓冲区,一个用来发送,一个用来接收

  • FIFO状态通过UART标志寄存器UARTFRUART接收状态寄存器(UARTRSR)显示。硬件监视空、满和溢出情况。

  • FIFO产生中断的触发条件由 UART中断FIFO深度选择(UARTIFLS)控制。两个FIFO可以单独配置为不同的电平情况下触发中断。可以选择如下配置:1/8、1/4、1/2、3/4、7/8。(例如:1/4代表连续FIFO装入16*1/4=4个字节产生一个接受中断

  • 复位后FIFO都是禁用的并作为1字节的保留寄存器,FIFO中断默认为两个都是1/2选项。通过UARTLCRHFEN位启用FIFO。

注意:关于复位后FIFO是默认使能还是禁用,似乎TI手册之间有矛盾,总之不要用默认设置,自己手动设置一下吧
以下内容来自ti的getting start手册

(5)中断、

如下介绍,建议结合相关的寄存器看,包括UARTCTL寄存器UARTIFLS寄存器

  • 接收超时中断:当FIFO不是空的,并且在32位期间没有接收到进一步的数据时触发
  • 接收中断:如果开启FIFO,当收数据>=FIFO深度时触发;否则每次接收到数据都触发
  • 发送中断:如果开启FIFO,当FIFO中数据<=FIFO深度时触发;否则在FIFO中没有数据时触发

三、编程实践

下面就按TIgetting start 手册的顺序进行UART实验吧

(1)UART配置和使用的基本流程


下面看一个官方例程,UART0实现echo

/*官方例程1*/
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
int main(void)
{SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);GPIOPinConfigure(GPIO_PA0_U0RX);GPIOPinConfigure(GPIO_PA1_U0TX);GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));UARTCharPut(UART0_BASE, 'E');UARTCharPut(UART0_BASE, 'n');UARTCharPut(UART0_BASE, 't');UARTCharPut(UART0_BASE, 'e');UARTCharPut(UART0_BASE, 'r');UARTCharPut(UART0_BASE, ' ');UARTCharPut(UART0_BASE, 'T');UARTCharPut(UART0_BASE, 'e');UARTCharPut(UART0_BASE, 'x');UARTCharPut(UART0_BASE, 't');UARTCharPut(UART0_BASE, ':');UARTCharPut(UART0_BASE, ' ');while (1){if (UARTCharsAvail(UART0_BASE)) UARTCharPut(UART0_BASE, UARTCharGet(UART0_BASE));}
}

官方对于程序的讲解如下

(2)使用类似C语言中stdio.h的方法

包含TivaWare提供的uartstdio.huartstdio.c文件,即可使用类似printf()等C函数

  • UART时钟、波特率配置函数需要从UARTConfigSetExpClk变为UARTStdioConfig
  • UARTprintf();的使用方法和C中printf()完全类似,支持%d等标准输入输出格式符

  • 特别注意一下,同一时间,只有一个串口可以用UARTprintfuartstdio.c中对printf重定向,默认是定向到UART0,我这里修改成UART1,如下

利用uartstdio改写上面的官方例程实现一样的功能,大家可以对比一下(我用的UART1,官方是UART0)

/*官方例程1改写,使用uartstdio*/
#include <stdint.h>
#include <stdbool.h>
#include "inc/tm4c123gh6pm.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/uart.h"
#include "uartstdio.h"
#include "driverlib/systick.h"
#include "driverlib/pin_map.h"int main(void)
{SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);//使能外设SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);//配置复用功能GPIOPinConfigure(GPIO_PB0_U1RX);GPIOPinConfigure(GPIO_PB1_U1TX);//分配UART信号GPIOPinTypeUART(GPIO_PORTB_BASE,GPIO_PIN_0|GPIO_PIN_1);//配置UART参数(这样配置可以用UARTprintf)UARTClockSourceSet(UART1_BASE, UART_CLOCK_PIOSC);   //使用16MHz内部高精度振荡器(PIOSC)作为UART模块时钟UARTStdioConfig(1,115200, 16000000);                          //UART编号、波特率、UART时钟频率(频率要和上一行设的一致)UARTprintf("Enter Text: \n");uint8_t getChar;while (1){getChar=UARTCharGet(UART1_BASE);UARTCharPut(UART1_BASE,getChar);}
}

(3)UART中断

进一步改进刚才的例程,使用接收中断代替主函数中的轮询检测,同时我们增加一个LED来指示数据接收和发送的情况

  1. 增加头文件inc/hw_ints.hdriverlib/interrupt.h(具体路径根据你的工程来)
  2. 进行中断配置,开启接受中断和超时中断`
  3. 配置指示用的LED
  4. 编写中断服务函数:这里首先要读中断状态寄存器,分析发生中断的种类;然后用读取的来清除中断标志(TM4C库函数中,中断标志返回值和清除中断标志函数的参数都是bit-packed格式,可以直接用,挺巧妙的);接下来读取并发送收到的数据;最后让led闪烁一下
  5. 别忘了注册中断服务函数,可以用函数注册,也可以手动修改中断像量表
#include <stdint.h>
#include <stdbool.h>
#include "inc/tm4c123gh6pm.h"             //Register Definitions
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
//#include "inc/hw_ints.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/uart.h"
#include "uartstdio.h"
#include "driverlib/systick.h"
#include "driverlib/pin_map.h"#define delay_ms(n); SysCtlDelay(n*(SysCtlClockGet()/3000));void UARTIntHandler(void)
{uint32_t ui32Status;ui32Status = UARTIntStatus(UART1_BASE, true);     //get interrupt statusUARTIntClear(UART1_BASE, ui32Status);             //clear the asserted interruptswhile(UARTCharsAvail(UART1_BASE))                //loop while there are chars{UARTCharPutNonBlocking(UART1_BASE, UARTCharGetNonBlocking(UART1_BASE)); //echo characterGPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2);     //blink LEDdelay_ms(1);GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0);            //turn off LED}
}int main(void)
{   SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);//使能外设SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);//配置复用功能GPIOPinConfigure(GPIO_PB0_U1RX);GPIOPinConfigure(GPIO_PB1_U1TX);//分配UART信号GPIOPinTypeUART(GPIO_PORTB_BASE,GPIO_PIN_0|GPIO_PIN_1);//LED配置SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);               //enable GPIO port for LEDGPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2);       //enable pin for LED PF2//串口参数设置UARTClockSourceSet(UART1_BASE, UART_CLOCK_PIOSC);           //使用16MHz内部高精度振荡器(PIOSC)作为UART模块时钟UARTStdioConfig(1,115200, 16000000);                      //UART编号、波特率、UART时钟频率(频率要和上一行设的一致)//中断使能IntMasterEnable();                                            //enable processor interruptsIntEnable(INT_UART1);                                      //enable the UART interruptUARTIntEnable(UART1_BASE, UART_INT_RX | UART_INT_RT);        //only enable RX and TX interrupts//注册中断服务函数UARTIntRegister(UART1_BASE,UARTIntHandler);UARTprintf("Enter Text: \n");while (1)                                                     //let interrupt handler do the UART echo function{  ;}
}

(4)FIFO测试

修改上述代码,测试FIFO的功能。
配置接收中断,当接收FIFO半满(8byte)时触发。利用串口调试助手一个char一个char发送。
观察到发送8个char后进入中断,FIFO测试成功

#include <stdint.h>
#include <stdbool.h>
#include "inc/tm4c123gh6pm.h"             //Register Definitions
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
//#include "inc/hw_ints.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/uart.h"
#include "uartstdio.h"
#include "driverlib/systick.h"
#include "driverlib/pin_map.h"#define delay_ms(n); SysCtlDelay(n*(SysCtlClockGet()/3000));void UARTIntHandler(void)
{uint32_t ui32Status;ui32Status = UARTIntStatus(UART1_BASE, true); //get interrupt statusUARTIntClear(UART1_BASE, ui32Status);                 //clear the asserted interruptswhile(UARTCharsAvail(UART1_BASE))                        //loop while there are chars{UARTCharPutNonBlocking(UART1_BASE, UARTCharGetNonBlocking(UART1_BASE)); //echo characterGPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2); //blink LEDdelay_ms(1);GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0); //turn off LED}
}int main(void)
{   SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);//使能外设SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);//配置复用功能GPIOPinConfigure(GPIO_PB0_U1RX);GPIOPinConfigure(GPIO_PB1_U1TX);//分配UART信号GPIOPinTypeUART(GPIO_PORTB_BASE,GPIO_PIN_0|GPIO_PIN_1);//LED配置SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);               //enable GPIO port for LEDGPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2); //enable pin for LED PF2//串口参数设置UARTClockSourceSet(UART1_BASE, UART_CLOCK_PIOSC); //使用16MHz内部高精度振荡器(PIOSC)作为UART模块时钟UARTStdioConfig(1,115200, 16000000);                          //UART编号、波特率、UART时钟频率(频率要和上一行设的一致)//FIFO配置,UARTFIFOLevelSet(UART1_BASE,UART_FIFO_TX4_8,UART_FIFO_RX4_8);   //FIFO填入半满(8byte)时触发中断UARTFIFOEnable(UART1_BASE);//中断使能IntMasterEnable();                                                                             //enable processor interruptsIntEnable(INT_UART1);                                                                  //enable the UART interruptUARTIntEnable(UART1_BASE, UART_INT_RX);  //注册中断服务函数UARTIntRegister(UART1_BASE,UARTIntHandler);UARTprintf("Enter Text: \n");while (1) //let interrupt handler do the UART echo function{    ;}
}

进一步进行其他FIFO中断测试,如下:

  • 打开FIFO的情况下,打开UART_INT_OE(FIFO溢出中断),此时FIFO深度无作用,FIFO接收17个(FIFO溢出)后进入中断,第17个byte丢失,会输出FIFO中存储的所有16个字符,特别注意FIFO溢出是一个错误引发的中断,在中断服务函数中,除了用UARTIntClear清除标志,还要写一句HWREG(UART1_BASE+UART_O_ECR)=0;清除错误标志,否则中断只能进一次。
  • 关闭FIFO的情况下(相当于FIFO深度为1),打开UART_INT_OE(FIFO溢出中断),连续收到两个byte溢出,在中断中打印第一个byte;打开UART_INT_RX(FIFO溢出中断),每收到一个byte都会进中断打印

四、部分库函数小结

(1)void UARTprintf(const char *pcString, …)

  1. 包含uartstdio.cuartstdio.h后可用
  2. 类似C语言printf()

(2)void UARTCharPut(uint32_t ui32Base, unsigned char ucData)

  1. 串口输出一个char型
  2. 等待FIFO中有数据再发送

(3)int32_t UARTCharGet(uint32_t ui32Base)

  1. 串口接收一个uint32_t型数据
  2. 等待FIFO中有数据再接收

(4)bool UARTCharPutNonBlocking(uint32_t ui32Base, unsigned char ucData)

  1. 串口输出一个char型
  2. 若发送时FIFO已满时,直接返回false而不在那循环等待

(5)int32_t UARTCharGetNonBlocking(uint32_t ui32Base)

  1. 串口接收一个uint32_t型数据
  2. 如果遇到接收时FIFO为空,直接返回false而不在那循环等待

(6)void UARTFIFOLevelSet(uint32_t ui32Base, uint32_t ui32TxLevel,uint32_t ui32RxLevel)

  1. 配置输入输出FIFO的深度

(7)void UARTFIFOEnable(uint32_t ui32Base)

  1. 开启某UART的FIFO功能

TM4C123G学习记录(6)--UART相关推荐

  1. TM4C123G学习记录(2)--GPIO

    为了准备电赛临时学一下TM4C123G,简单记录学习内容 大家可以在这里下载我收集的资源,非常全面,花了很大功夫收集来的,还有书籍.例程代码等 还可以在TI官网下载相关文档TI官网 一.实验简介 简单 ...

  2. TM4C123G学习记录(5)--PWM输出

    因为想申请 CSDN 博客认证需要一定的粉丝量,而我写了五年博客才 700 多粉丝,本文开启关注才可阅读全文,很抱歉影响您的阅读体验 为了准备电赛临时学一下TM4C123G,简单记录学习内容 大家可以 ...

  3. K210学习记录(2)——UART(串口)

    0.引言 本系列博客仅作为本人学习K210单片机的学习记录,主要学习其内部资源使用,作为初学者难免有错误之处,如有发现还望指出. 硬件:Sipeed Maix Dock开发板(推荐官方KD233开发板 ...

  4. 【转】BLE 学习记录

    原文网址:http://m.blog.csdn.net/blog/chiooo/43985401 BLE 学习记录 ANROID BLE 开发,基于 bluetoothlegatt 分析 mBluet ...

  5. 基于全志A33开发板linux系统移植学习记录(Boot0)

    基于全志A33开发板linux系统移植学习记录 第一章 Boot0基于ARMGCC的编译与修改 文章目录 基于全志A33开发板linux系统移植学习记录 前言 一.全志A33简介以及上电引导流程 二. ...

  6. 主线剧情01-ARM-IMX6ULL基础学习记录

    ARM & i.MX6ULL 基础学习记录 编辑整理 by Staok 本文大部分内容摘自"100ask imx6ull"开发板的配套资料(如<IMX6ULL裸机开发 ...

  7. 学习记录--蓝牙模块HC05(串口收发)

    主要实现:PC上位机与蓝牙之间的通信(收发) 一,HC05模式等一系列设置 参考博客: (11条消息) stm32之蓝牙模块HC-05使用_一剃解千愁的博客-CSDN博客_stm32蓝牙模块的使用 ( ...

  8. MSP432单片机学习记录(二)

    文章目录 1.复位视图 2.代码提示 3.新建自己的硬件库(hardware) 4.中断的使用 前面的文章提到了ccs工程的创建,下面继续介绍msp432的使用,上一篇文章链接如下所示:MSP432单 ...

  9. Pytorch学习记录-torchtext和Pytorch的实例( 使用神经网络训练Seq2Seq代码)

    Pytorch学习记录-torchtext和Pytorch的实例1 0. PyTorch Seq2Seq项目介绍 1. 使用神经网络训练Seq2Seq 1.1 简介,对论文中公式的解读 1.2 数据预 ...

最新文章

  1. 表白这件事,比解 bug 要难多少?
  2. CodeSmith 学习资料收集
  3. 一款全屏图片滑动js 插件 超快捷
  4. PHP过滤器 filter_has_var() 函数
  5. Vishay将MCW 0406 AT系列精密宽端子薄膜片式电阻欧姆值降至业内最低
  6. 网络推广离不开关键词的精准挖掘
  7. 怎样将employee 加到Territory里
  8. 查询已有链表的hashmap_原创 | 面试不再慌,看完这篇保证让你写HashMap跟玩一样...
  9. 0.1uf与47uf并联_UF是什么形式?
  10. 判断一个字符串的字符是不是唯一
  11. 黑苹果 电脑关机是因为发生了问题_【电脑常识】常见的电脑误区,你中了几点?...
  12. 封装制作ghost xp,含加入域帐号配置迁移脚本。
  13. 【转载】深入浅出讲解FOC算法与SVPWM技术——自制FOC驱动器
  14. php给发qq消息,PHP 模拟QQ登录及发送消息实现方法
  15. java中设置5秒后跳转_javaweb 3秒后自动跳转的几种方式
  16. “大学教育的目的”-- 芝加哥大学Andrew Abbott教授的演讲
  17. 数据视化Echarts+百度地图API实现市县区级下钻
  18. 机器学习基础 维基翻译 保序回归 随机森林 Pipeline处理 及简单的sklearn例子
  19. 用C++写出求矩形和圆形面积的程序
  20. 管理经济学第一遍总结

热门文章

  1. python 打包exe_python pyinstaller打包exe报错的解决方法
  2. C++ CoreDump
  3. 从零开始学习使用VUE搭建一个管理系统页面
  4. Java中的变量名命名规则
  5. 图片裁剪工具之cropper.js
  6. 996的大公司和965的小公司,你怎么选?
  7. oracle科目余额表的查询,科目余额表查询 · selfaccount-services · 看云
  8. QT 利用QPixmap复制图片
  9. 微博爬虫——爬取指定范围内所有帖子包含的定位信息的方法
  10. Git上传代码文件至Github