电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
【dsPIC33】UART收发数据
分 享
扫描二维码分享
【dsPIC33】UART收发数据
dsPIC33
UART
KVIN
关注
发布时间: 2019-10-10
丨
阅读: 1633
# 前言 串口是一个非常重要的工具,用这个可以非常简单的收发一些数据,串口的操作还是比其他协议简单很多,因此在工控芯片上串口非常普遍。本节就详细记录dsPIC33E芯片的串口寄存器配置以及使用过程。 首先需要把串口的硬件环境搭建好,我这里使用了一对蓝牙主从机,蓝牙主机连接USB转TTL模块连接电脑,蓝牙从机连接单片机芯片,蓝牙的无线传输距离还是比较短的,有效距离只有10几米,不过无所谓了,重点并不是距离,只需要它能够正常收发即可,连接图如下: ![](https://cf02.ickimg.com/bbsimages/201909/9eaccb206847f298789222c9ad463ed3.png) 我将蓝牙主从机包括密码,名字,波特率等配置好后,测试他们两个之间的数据交互是没问题的,也就是确保了蓝牙是正常的。之后便可以开始UART的配置过程。 ## 1.第一步:配置引脚复用 第一步配置肯定就是引脚配置了,需要把指定的引脚配置为UART模式,包括TX,RX引脚,查看手册中的IO端口章节: ![](https://cf02.ickimg.com/bbsimages/201909/5580c223ca04f9b9c7af93a84032f35f.png) 这句话也就是说,如果该端口由AD/DA功能,那么如果要使用这个端口的数字功能,就要将ANSELx寄存器相应的位置0。 ![](https://cf02.ickimg.com/bbsimages/201909/782ffc6e58d4b56c9ea6699ba3135480.png) 也就是说,如果使用UART功能,相关引脚不能使用PORT和TRIS寄存器来进行读写操作。这个关系不大,应该不会有这样的操作。 ### 输入映射与输出映射: 需要知道可用的引脚以及引脚对应的外设: ![](https://cf02.ickimg.com/bbsimages/201909/5f4f90a2ba94215902f8b59a5775c3a4.png) 这里就需要我们在查看芯片手册中,我们具体的芯片型号对应的电路中需要的引脚是什么编号,也就是说查找RPn。 ![](https://cf02.ickimg.com/bbsimages/201909/b820c04a16ecd70093d154c6c430513f.png) ![](https://cf02.ickimg.com/bbsimages/201909/5c853c99781f0e6957ca47b2e4e59b90.png) 由上可知,TX是RP40,RX是RP41。 如果使用RX接收引脚,需要配置输入映射:(RPINRx寄存器) ![](https://cf02.ickimg.com/bbsimages/201909/5107a0898c4991c650ff9717f2b2dac9.png) ![](https://cf02.ickimg.com/bbsimages/201909/24aca27488568c732fc97d5f025db126.png) 如果使用TX发送引脚,需要配置输出映射:(RPORx寄存器) ![](https://cf02.ickimg.com/bbsimages/201909/8571b4e0bf56b1657603517f40bea9aa.png) ### 配置TX: 配置引脚为TX首先需要禁用引脚的模拟模式,将引脚配置为IO,之后配置为输出: ```c ANSELBbits.ANSB8 = 0; //关闭模拟模式,设置B9为数字IO TRISBbits.TRISB8 = 0; //设置B8为输出 ``` 之后,便将此引脚配置为UART1_TX功能: ![](https://cf02.ickimg.com/bbsimages/201909/d7545fb83c2291bf93041b729a3a4c93.png) 也即,需要将RPOR寄存器的RP40位中写入二进制的000001,也就是0b000001: ```c RPOR3bits.RP40R = 0b000001; //选择为TX模式 ``` ### 配置RX: ![](https://cf02.ickimg.com/bbsimages/201909/cf7a1b0790405cfcf1861fd71d4ce7e4.png) 也就是说要把RPINR18寄存器的U1RXR位接入需要接入的引脚,电路上是PB9,也就是PR41,就配置位了RX模式,在此之前要把此引脚设置为输入。 ![](https://cf02.ickimg.com/bbsimages/201909/9485bbe46cad7259bcbf08cd33c83478.png) ## 2.第二步:配置波特率 ![](https://cf02.ickimg.com/bbsimages/201909/34173ba1df3505b1bd332f5229416199.png) 波特率就很好配置了,按照这个图,配置相应的BRGH位,然后根据BRGH位计算,这里我使用的BRGH就为0,由于我配置的时钟频率为60M,(关于时钟频率配置,请看此dsPIC系列的振荡器相关文章)按照这个公式计算即可,波特率宏定义: ```c #define FCY 60000000 //工作频率 #define BAUDRATE 9600 //设定波特率 #define BRGVAL ((FCY/BAUDRATE)/16)-1 ``` ## 3.第三步:发送功能程序 完成TX配置之后,就需要编写发送函数,从主要的还是发送一个字节函数,只要可以发送一个字节,那么发送字符串函数什么的,就可以迎刃而解。发送功能函数的最主要的就是数据缓冲区以及发送完成标志: ![](https://cf02.ickimg.com/bbsimages/201909/c765dc53a0d55397aca064306459098e.png) 则,发送函数编写就可以这样: ```c void uart_SendByte (uint8_t val) { U1TXREG = val; //将数据写入发送缓冲区 /@@*等待发送完成*/ while(!U1STAbits.TRMT); //等待发送移位寄存器为空 即上次发送已完成 } ``` 完整TX配置以及发送函数如下: ```c /@@****************发送配置***************/ ANSELBbits.ANSB8 = 0; //关闭模拟模式,设置B9为数字IO TRISBbits.TRISB8 = 0; //设置B8为输出 RPOR3bits.RP40R = 0b000001; //选择为TX模式 U1MODEbits.STSEL = 0;//一个停止位 U1MODEbits.PDSEL = 0;//8数据位 无奇偶校验 U1MODEbits.ABAUD = 0;//禁止波特率测量或测量已完成 U1MODEbits.BRGH = 0;//BRG 在每个位周期内产生 16 个时钟信号 ( 16 倍频波特率时钟,标准模式) U1BRG = BRGVAL; //60MHz波特率9600(按照计算公式) U1STAbits.UTXISEL0 = 0; U1STAbits.URXISEL1 = 0;//当接收到一个字符且该字符从 UxRSR 传输给接收缓冲区, //使接收缓冲区有一个或多个字符时,中断标志位置 1。 IEC0bits.U1TXIE = 0; //不使能发送中断 U1MODEbits.UARTEN = 1;//使能UART U1STAbits.UTXEN = 1; //使能发送 void uart_SendByte (uint8_t val) { U1TXREG = val; //将数据写入发送缓冲区 /@@*等待发送完成*/ while(!U1STAbits.TRMT); //等待发送移位寄存器为空 即上次发送已完成 } ``` 我使用了此函数在main函数中一直发送 ff,测试效果如图: ![](https://cf02.ickimg.com/bbsimages/201909/160064117f7222cd254184fd91a8f963.png) ## 4.第四步:接收功能程序 接收部分就使用中断会更好一些,因此,需要配置RX的中断: ![](https://cf02.ickimg.com/bbsimages/201909/8868005ce8fc5e305b00626f80dd91d2.png) 配置代码: ```c TRISBbits.TRISB9 = 1; //设置B9为输入 RPINR18bits.U1RXR = 41; //设置B9为RX模式 U1MODEbits.STSEL = 0;//一个停止位 U1MODEbits.PDSEL = 0; // 8数据位 无奇偶校验 U1MODEbits.ABAUD = 0; // 禁止波特率测量或测量已完成 U1MODEbits.BRGH = 0; // BRG 在每个位周期内产生 16 个时钟信号 ( 16 倍频波特率时钟,标准模式) U1BRG = BRGVAL;//80MHz波特率9600(按照计算公式) U1STAbits.URXISEL = 0b00;//当接收到一个字符且该字符从 UxRSR 传输给接收缓冲区, //使接收缓冲区有一个或多个字符时,中断标志位置 1。 U1STAbits.ADDEN = 1; IEC0bits.U1RXIE = 1;//使能接收中断 IPC2bits.U1RXIP = 0b100; //接收中断优先级设置为4 U1MODEbits.UARTEN = 1;//使能UART void __attribute__((__interrupt__, auto_psv)) _U1RXInterrupt(void)//接收中断 { uint8_t data = 0; IFS0bits.U1RXIF = 0; data = U1RXREG; if(data == 0xff) { PORTBbits.RB4 = 0; //点亮LED } else { PORTBbits.RB4 = 1; //熄灭LED } } ``` 上面接收部分的功能就是电脑发送 ff ,则点亮LED1,发送其他数据则熄灭LED1,效果如下: 如上所示:当发送 ff 时,丝印编号为D1的LED点亮,发送其他时,D1熄灭(可能由于GIF转换的原因有些模糊,因为GIF只能上传6M大小的,所以只能想办法压缩了)。 ![](https://cf02.ickimg.com/bbsimages/201909/152db049e95b62f07add348855c466a7.gif) 当然,也可以做一个更有趣的实验,既然用电脑的串口软件可以控制了,那么用手机蓝牙自然也是可以控制的,因为手机自带蓝牙,因此就不需要哪个USB转TTL以及蓝牙主机了,之间下载一个蓝牙app即可,我下载了一个蓝牙串口app,可以自定义按键发送的内容,那么就可以近距离无线控制我的板子上的led灯了,效果: ![](https://cf02.ickimg.com/bbsimages/201909/fe17c869ba64135b2e7654730d57e787.gif)
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
KVIN
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交