BS86D20C合泰芯片教程08——串口通信
今天我们来了解一下合泰芯片的串口通信,先来看一下核心板电路,可以发现PA3是RX口,PA7是TX口,但是PA7口在前面的蜂鸣器驱动中复用为GPIO口,在使用前需要把0R电阻JR1拆掉,否则可能会出现奇奇怪怪的问题。

看到芯片手册163页,流程图展示了数据发送和接收流程,数据发送时先发到TXR寄存器然后送到移位寄存器发送数据,数据从低位到高位发出。接收时移位寄存器先接收,然后再发送,在发送和接收时速率都是由波特率发生器控制。
在164页的UARTn数据传输方案中,对数据传输的流程也有详细的描述,但是要注意接收寄存器和发送寄存器是共用一个数据寄存器,也就是说发送和接收的数据都在一个地方,如果发生冲突,例如中断接收把发送的数据冲掉,那此时发送的数据是有问题的,一般不会遇到,但是在同时接收和发送数据时需要注意。
接下来开始配置寄存器,一共有5个寄存器,UnSR是只读寄存器,这个寄存器会存储UART的状态,我们无需配置。第二个是控制寄存器,Bit7是使能UART,所以设置为1,发送数据位选择8Bit,Bit6=0;无奇偶校验,Bit5-4均为0;停止位为1,Bit3为0;暂停字设置无,Bit2为0;Bit1为只读,设置为0;Bit0是发送9位数据才有效,这里无需配置,也默认为0;UnCR1寄存器配置为0x10000000=0x80。
然后是UnCR2寄存器配置,这里Bit7是UARTn的发送使能,配置为1;Bit6的RXENn是接收使能,配置为1;Bit5是波特率的速度选择,这里设置为低速,配置为0;Bit4的地址位检测设置为0;Bit3无需配置,设置为0;Bit2是接收中断使能,配置为1;Bit1的发送空闲中断使能配置为0;Bit0的寄存器为空也选择默认,配置为0。因此UNCR2为0x11000100=0xc4。

TXR_RXRn是数据寄存器,用来存储发送和接收的数据,这里我们配置为0xff,0x00等都没有影响。BRGn寄存器是设置波特率的寄存器,在前面设置UnCR2时会影响到这里的速度,这里我们把波特率设置为9600,带入公式也就是:9600=fH/[64*(N+1)],,fH为8M,解得N=12,所以这里配置为BRGn=0x0c。这里带入公式有朋友可能有疑惑,算一下不难发现N不是刚刚好等于12,有一定的误差,但是不影响我们使用。

配置完串口通信的基础后,看到178页的中断地图,可以看到UART0中断在优先级比较低的地方,先打开UART0的中断,UR0E=0,然后开启总中断,EMI=0。到这里我们已经配置完串口通信的基础设置,然后来写一个简单的逻辑,用核心板发送字符串1和2,分别控制PB6和7的两个LED,让他们不断翻转,并且速度不能太快。
代码写完后可以使用USB转ttl来和核心板通信,如果手上有两个核心板也可以同时烧录这个程序,都可以实现上述功能。在这里笔者用两种方式都尝试过,在最开始代码逻辑没写好,遇到总线冲突,发现用USB转ttl单独通信没问题,两块核心板通信就会出问题,花费一点时间后找到原因,调了代码的顺序就解决了这个问题。
#include "BS86D20C.h"
#define u16 unsigned int
#define u8 unsigned char
#define IN 1 // 引脚方向:输入
#define OUT 0 // 引脚方向:输出
#define ON 1 // LED 亮
#define OFF 0 // LED 灭
unsigned int a; // 主循环计数器,用于“软件延时”
volatile u8 recdata = 0; // 串口收到的最新字节,由中断写入
void delay_ms(u16 ms)
{
while(ms--)
{
GCC_DELAY(2000); // 约 1 ms(8 MHz 时 2000 个空指令周期)
GCC_CLRWDT(); // 喂狗,防止 WDT 复位
}
}
//UART串口通信
void UART_SendChar(u8 data)
{
if(_txif0) // TX 寄存器空才可写
{
_txr_rxr0 = data; // 写入 TXR,同时硬件清 TXIF
while(!_txif0); // 等待数据被移入移位寄存器
while(!_tidle0); // 等待全部位发送完毕
}
}
void SendString(u8 *ch)//发字符串
{
while(*ch!=0) // 遇到 '\0' 结束
{
UART_SendChar(*(ch++));
}
}
void main()
{
/* ---- 1. 配置 LED 引脚 ---- */
_pbc6 = OUT; // PB6 设为输出
_pbc7 = OUT; // PB7 设为输出
_pb6 = ON; // LED1 初始亮
_pb7 = OFF; // LED2 初始灭
/* ---- 2. 配置 UART 引脚 ---- */
_pac7 = 0; // PA7 设为输出(TX)
_pa7 = 1; // TX 默认高
_pac3 = 1; // PA3 设为输入(RX)
_papu3 = 1; // RX 开内部上拉
/* ---- 3. 配置 UART 寄存器 ---- */
_u0cr1 = 0x80; // 使能 UART0,8 位数据
_u0cr2 = 0xC4; // 允许发送、接收,1 位停止位
_txr_rxr0 = 0xFF; // 先清一次 RX 寄存器
_brg0 = 0x0c; // 波特率 9600(8 MHz 时钟)
/* ---- 4. 开中断 ---- */
_ur0e = 1; // 允许 UART0 接收中断
_emi = 1; // 开总中断
delay_ms(20); // 上电后等晶振稳定
while (1)
{
a++; // 计数器自增
_clrwdt();//喂狗
if(a>65534)//自增延时,如果a=65535(最大值,再大就溢出),发送1,2
{
SendString((u8*)"1\n");
SendString((u8*)"2\n");
a = 0;
}
if (recdata != 0)
{
if (recdata == '1')
{
_pb6 = ~_pb6;
}
else if (recdata == '2')
{
_pb7 = ~_pb7;
}
recdata = 0; // 清接收标志,准备下一字节
}
}
}
DEFINE_ISR(UART_Int, 0x28) // 向量 0x28 对应 UART0 中断
{
if (_rxif0) // 如果收到新字节
{
recdata = _txr_rxr0; // 读取 RX 寄存器,同时硬件清 RXIF
}
}
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)