精华内容
下载资源
问答
  • 2305驱动/CHK35XDRV驱动
  • PIC串口发送接收多字节

    热门讨论 2012-07-14 08:52:14
    PIC单片机的串口通信,能够接收发送任意多个字节,通过proteus仿真,设置虚拟串口,可以与串口助手联合调试,希望大家共同交流
  • 单片机程序串口通讯下载,,,,,,,,,,,,
  • PIC 串口程序 模拟串口
  • PIC串口程序

    2013-11-16 18:11:39
    PIC16F887A或者PIC16F1933等PIC单片机的串口发送程序,在程序中放入便于调试。
  • PIC串口应用的C程序实现
  • PIC单片机精通_串口通信模块C实现

    千次阅读 2016-11-15 14:33:03
    1.串口通讯头/定义文件 usart.h #ifndef _SERIAL_H_ #define _SERIAL_H_ #define BAUD 9600 #define FOSC 9216000L #define NINE 0 /* Use 9bit communication? FALSE=8bit */ #define DIVIDER ((int)(FOS

    1.串口通讯头/定义文件 usart.h


    #ifndef _SERIAL_H_
    #define _SERIAL_H_
    
    #define BAUD 9600      
    #define FOSC 9216000L
    #define NINE 0     /* Use 9bit communication? FALSE=8bit */
    
    #define DIVIDER ((int)(FOSC/(16UL * BAUD) -1))
    #define HIGH_SPEED 1
    
    #if NINE == 1
    #define NINE_BITS 0x40
    #else
    #define NINE_BITS 0
    #endif
    
    #if HIGH_SPEED == 1
    #define SPEED 0x4
    #else
    #define SPEED 0
    #endif
    
    #if defined(_16F87) || defined(_16F88)
    	#define RX_PIN TRISB2
    	#define TX_PIN TRISB5
    #else
    	#define RX_PIN TRISC7
    	#define TX_PIN TRISC6
    #endif
    
    /* Serial initialization */
    //'\'是对函数内属性的定义 不可缺少
    #define init_comms()\
    	RX_PIN = 1;	\
    	TX_PIN = 1;		  \
    	SPBRG = DIVIDER;     	\
    	RCSTA = (NINE_BITS|0x90);	\
    	TXSTA = (SPEED|NINE_BITS|0x20)
    
    void putch(unsigned char);
    unsigned char getch(void);
    unsigned char getche(void);
    
    #endif

    2.串口通讯源/实现文件 usart.c

    /******************************************/
    /*Author:Shen Chucu  All Rights Reserved!**
    /*Tsinghua University
    /*2016-11-15
    /********************************************/
    #include <pic.h>
    #include <stdio.h>
    #include "usart.h"
    __CONFIG(0x3ffa);
    
    
    void delay(unsigned int x);
    static int label=0; //不做事件响应
    void main()
    {
       INTCON=0x00;
       GIE=1;
       PEIE=1;
       RCIE=1;
       init_comms();
       CREN=1;
       SPEN=1;
       while(1)
       {//等待中断 并进行事件响应设定
         if(label==1)
          {
            printf("OK"); 
    		label = 0; //发送一个回馈信号即可
            delay(50);
          }
         if(label==2)
         {
            printf("ERROR");
        	label = 0; //发送一个回馈信号即可
            delay(50);
          }   
       }
    }  
    
    void interrupt IsReceive()
    {  
       if(RCIE&&RCIF==1) //接受中断使能位 + 接收中断标志位
        {
            unsigned char temp=RCREG;  //把上位机发送的数据保存下来
            if(temp=='S')
              { 
                label=1;   //发送数据标志 1
              } 
           else if(temp=='E')
                 {
                   label=0; //发送数据标志 0 
                 }
                 else 
                   label=2;  //发送数据标志 2  
        }
    }
    
    void delay(unsigned int x)
    {
        unsigned int a,b;  //延时时间110x
        for(a=x;a>1;a--)
           for(b=110;b>1;b--)
              ;
    } 


    展开全文
  • PIC串口通信程序

    2013-03-07 22:03:37
    PIC串口通信程序 简单的pic串口程序 简单的pic串口程序
  • PIC串口编程器配套文件 这个很不错啊,很难得的
  • PIC 串口通信

    2012-09-16 14:02:44
    PIC 串口通信 见到的C语言串口通信,入门
  • PIC系列模拟串口

    2017-11-22 10:11:13
    PIC模拟串口,波特率9600,发送接收测试OK,支持IO口,
  • pic串口调试程序。串口接收和发送程序,通过接收调试串口。
  • 本文给大家分享了一个PIC读写内部EEPROM的程序(c)。
  • PIC单片机串口驱动程序

    热门讨论 2010-08-06 14:06:56
    PIC单片机串口驱动程序,使用起来还是蛮方便的。
  • 一部分网上的资料,一部分自己写的,希望对大家有用。
  • PIC串口通信

    2012-08-13 16:15:34
    编译通过的UART串口 使用中断接收,特别对于无法接收的朋友
  • PIC串口波特率计算工具,用于PIC单片机串口波特率计算
  • hs12864与PIC串口通信

    2014-03-25 12:25:06
    hs12864与PIC串口通信,注意接口的初始化,以及hs128的连线。
  • 关于PIC单片机串口数据接收,如果数据接口一直可以检测数据,那么即使关闭RCIE,实际上也会接收数据,当数据源源不断地进来时,你再使能RCIE的时候其实也只能接收到关闭之后的两个数据,此后再也无法进入中断。...
  • 两种PIC串口下载线

    2010-04-25 14:08:04
    两种PIC 串口下载线 PROTEL99原理图,与众位共享!
  • 针对PIC32单片机,串口部分熟悉,并使用Harmony进行工程配置及数据收发,并结合开发板验证测试。

    PIC系列-串口通讯模块

    1、PIC32参考资源

    2、串口通讯描述

    3、寄存器介绍

    4、UART 发送器

    5、UART接收器

    6、使用Harmony配置串口收发

    7、实际代码分析

    8、实验验证


    1、PIC32参考资源

    PIC32系列参考手册 中文版  链接地址:PIC32系列参考手册 第21章 UART 模块

    2、串口通讯描述

    通用异步收发器模块是 PIC32MX 系列器件提供的串行 I/O 模块之一。

    UART 模块的主要特性有:

    • 全双工 8 位或 9 位数据传输

    • 偶校验、奇校验或无奇偶校验选项 (对于 8 位数据)

    • 一个或两个停止位

    • 硬件自动波特率特性

    • 完全集成的波特率发生器,具有 16 位预分频器

    • 当器件工作在 80 MHz 时,波特率范围从 76 bps 至 20 Mbps

    • 独立的接收和发送 FIFO 数据缓冲区

    • 奇偶校验、帧和缓冲区溢出错误检测

    • 支持仅在地址检测 (第 9 位 = 1)时产生中断

    • 独立的发送和接收中断

    • 用于诊断支持的环回模式

    • LIN 1.2 协议支持

    下图是UART的简化框图,主要有波特率发生器、异步发送器、异步接收器和IrDA编解码器。

    3、寄存器介绍

    控制寄存器

    每个 UART 模块包含以下特殊功能寄存器

    • UxMODE:UARTx 模式寄存器

    • UxSTA:UARTx 状态和控制寄存器

    • UxTXREG:UARTx 发送寄存器

    • UxRXREG:UARTx 接收寄存器

    • UxBRG:UARTx 波特率寄存器

    每个 UART 模块还具有用于中断控制的相关位

    • UxTXIE:发送中断允许控制位

    • UxTXIF:发送中断标志状态位

    • UxRXIE:接收中断允许控制位

    • UxRXIF:接收中断标志状态位

    • UxEIE:错误中断允许控制位

    • UxEIF:错误中断标志状态位

    • UxIP<2:0>:中断优先级控制位

    • UxIS<1:0>:中断子优先级控制位

    UxMODE :UARTx 模式寄存器

     bit 15 ON :UARTx 使能位

    1 = 使能 UARTx ; UARTx 根据 UEN<1:0> 和 UTXEN 控制位的定义控制 UARTx 引脚

    0 = 禁止 UARTx ;由 PORTx、TRISx 和 LATx 寄存器中的相应位控制所有 UARTx 引脚; UARTx 的功耗最小

    bit 14 FRZ :调试异常模式冻结位

    1 = 在 CPU 处于调试异常模式时冻结工作

    0 = 在 CPU 处于调试异常模式时继续工作

    bit 13 SIDL :空闲模式停止位

    1 = 在器件进入 Idle(空闲)模式时停止工作

    0 = 在 Idle (空闲)模式下继续工作

    bit 12 IREN :IrDA 编码器和解码器使能位

    1 = 使能 IrDA

    0 = 禁止 IrDA

    bit 11 RTSMD :UxRTS 引脚模式选择位 (4)

    1 = UxRTS 引脚处于单工模式

    0 = UxRTS 引脚处于流控制模式

    bit 9-8 UEN<1:0> :UARTx 使能位

    11 = 使能并使用 UxTX、 UxRX 和 UxBCLK 引脚; UxCTS 引脚由 PORTx 寄存器中的相应位控制

    10 = 使能并使用 UxTX、 UxRX、 UxCTS 和 UxRTS 引脚

    01 = 使能并使用 UxTX、 UxRX 和 UxRTS 引脚; UxCTS 引脚由 PORTx 寄存器中的相应位控制

    00 = 使能并使用UxTX和UxRX引脚;UxCTS和UxRTS/UxBCLK引脚由PORTx寄存器中的相应位控制

    bit 7 WAKE :在休眠模式下检测到启动位唤醒使能位

    1 = 使能唤醒

    0 = 禁止唤醒

    bit 6 LPBACK :UARTx 环回模式选择位

    1 = 使能环回模式

    0 = 禁止环回模式

    bit 5 ABAUD :自动波特率使能位

    1 = 使能对下一个字符的波特率测量——需要接收同步字符 (0x55);完成时由硬件清零

    0 = 禁止波特率测量或测量已完成

    bit 4 RXINV :接收极性翻转位

    1 = UxRX 的空闲状态为 0

    0 = UxTX 的空闲状态为 1

    bit 3 BRGH :高波特率使能位

    1 = 高速模式——使能 4x 波特率时钟

    0 = 标准速度模式——使能 16x 波特率时钟

    bit 2-1 PDSEL<1:0> :奇偶校验和数据选择位

    11 = 9 位数据,无奇偶校验

    10 = 8 位数据,奇校验

    01 = 8 位数据,偶校验

    00 = 8 位数据,无奇偶校验

    bit 0 STSEL :停止选择位

    1 = 2 个停止位

    0 = 1 个停止位

    UxSTA :UARTx 状态和控制寄存器

    bit 24 ADM_EN :自动地址检测模式使能位

    1 = 使能自动地址检测模式

    0 = 禁止自动地址检测模式

    bit 23-16 ADDR<7:0> :自动地址掩码位

    当 ADM_EN 位为 1 时,该值定义用于自动地址检测的地址字符。

    bit 15-14 UTXISEL<1:0> :发送中断模式选择位

    对于 UART1 和 UART2 模块:

    11 = 保留,不要使用

    10 = 当发送缓冲区变为空时产生中断

    01 = 当发送完所有字符时产生中断

    00 = 当发送缓冲区变为未满 (至少有一个数据空间为空)时产生中断

    对于 UART1A、 UART1B、 UART2A、 UART2B、 UART3A 和 UART3B 模块:

    11 = 保留,不要使用

    10 = 当发送缓冲区为空时产生中断并将中断标志位置为有效

    01 = 当发送完所有字符时产生中断并将中断标志位置为有效

    00 = 当发送缓冲区至少有一个数据空间为空时产生中断并将中断标志置为有效

    bit 13 UTXINV :发送极性翻转位

    如果禁止 IrDA 模式 (即, IREN (UxMODE<12>)为 0):

    1 = UxTX 的空闲状态为 0

    0 = UxTX 的空闲状态为 1

    如果使能 IrDA 模式 (即, IREN (UxMODE<12>)为 1):

    1 = IrDA 编码的 UxTX 空闲状态为 1

    0 = IrDA 编码的 UxTX 空闲状态为 0

    bit 12 URXEN :接收器使能位

    1 = 使能 UARTx 接收器,由 UARTx 控制 UxRX 引脚 (如果 ON = 1)

    0 = 禁止 UARTx 接收器, UARTx 模块忽略 UxRX 引脚。由端口控制 UxRX 引脚。

    bit 11 UTXBRK :发送间隔位

    1 = 在下次发送时发送间隔字符——启动位后跟随 12 个 0 位,然后是停止位;完成时由硬件清零

    0 = 禁止或已完成间隔字符的发送

    bit 10 UTXEN :发送使能位

    1 = 使能 UARTx 发送器,由 UARTx 控制 UxTX 引脚 (如果 ON = 1)

    0 = 禁止 UARTx 发送器,中止所有等待的发送,缓冲区复位。由端口控制 UxTX 引脚。

    bit 9 UTXBF :发送缓冲区满状态位 (只读)

    1 = 发送缓冲区已满

    0 = 发送缓冲区未满,至少还可再写入一个字符

    bit 8 TRMT :发送移位寄存器空位 (只读)

    1 = 发送移位寄存器为空,同时发送缓冲区为空 (上一次发送已完成)

    0 = 发送移位寄存器非空,发送在进行中或在发送缓冲区中排队

    bit 7-6 URXISEL<1:0> :接收中断模式选择位

    对于 UART1 和 UART2 模块:

    11 = 当接收缓冲区变满 (即,有 4 个数据字符)时,中断标志位置 1

    10 = 当接收缓冲区 3/4 满 (即,有 3 个数据字符)时,中断标志位置 1

    0x = 当接收到一个字符时,中断标志位置 1

    对于 UART1A、 UART1B、 UART2A、 UART2B、 UART3A 和 UART3B 模块:

    11 = 保留;不要使用

    10 = 当接收缓冲区 3/4 满或更满 (即,有 6 个或更多数据字符)时,中断标志位置为有效

    01 = 当接收缓冲区 1/2 满或更满 (即,有 4 个或更多数据字符)时,中断标志位置为有效

    00 = 当接收缓冲区非空 (即,至少有 1 个数据字符)时,中断标志位置为有效

    bit 5 ADDEN :地址字符检测位 (接收数据的 bit 8 = 1)

    1 = 使能地址检测模式。如果没有选择 9 位模式,该控制位不起作用。

    0 = 禁止地址检测模式

    bit 4 RIDLE :接收器空闲位 (只读)

    1 = 接收器空闲

    0 = 正在接收数据

    bit 3 PERR :奇偶校验错误状态位 (只读)

    1 = 检测到当前字符的奇偶校验错误

    0 = 未检测到奇偶校验错误

    bit 2 FERR :帧错误状态位 (只读)

    1 = 检测到当前字符的帧错误

    0 = 未检测到帧错误

    bit 1 OERR :接收缓冲区溢出错误状态位

    该位由硬件置 1,且只能用软件清零 (= 0)。清零原来置 1 的 OERR 位将使接收缓冲区和 RSR 复位为空状态。

    1 = 接收缓冲区已溢出

    0 = 接收缓冲区未溢出

    bit 0 URXDA :接收缓冲区数据存在标志位 (只读)

    1 = 接收缓冲区中有数据,至少还有一个字符可被读取

    0 = 接收缓冲区为空

    UxTXREG :UARTx 发送寄存器

     bit 8-0 TX<8:0> :待发送字符的 bit 8-0 数据位

    UxRXREG :UARTx 接收寄存器

     bit 8-0 RX<8:0> :已接收字符的 bit 8-0 数据位

    UxBRG :UARTx 波特率寄存器

     bit 15-0 BRG<15:0> :波特率分频比位

    UART 波特率发生器

    UART 模块包含一个专用的 16 位波特率发生器。UxBRG 寄存器控制一个自由运行的 16 位定时器的周期。

    串口波特率 = 串口时钟频率/[速度模式*(波特率分频比+1)]

    波特率分频比 = 串口时钟频率/[速度模式*串口波特率] - 1

    速度模式:高速模式时为4,标准速度模式时为16;

    BCLKx 输出

    如果使能了 UART 和 BCLKx 输出(即,UEN<1:0> 位(UxMODE<9:8>)= 11),则 BCLKx 引脚将输出 16x 波特率时钟。此功能用于支持外部 IrDA 编 / 解码器 (见图 21-2)。在休眠模式下,BCLKx 输出保持低电平。只要 UART 保持在该模式(即,UEN<1:0> 位(UxMODE<9:8>)= 11),则无论 PORTx 和 TRISx 锁存位状态如何, BCLKx 都强制为输出。

    UART 配置

    UART 使用标准的不归零(Non-Return-to-Zero,NRZ)格式(1 个启动位、8 或 9 个数据位和1 或 2 个停止位)。硬件提供奇偶校验,可由用户配置为偶校验、奇校验或无奇偶校验。最普通的数据格式是 8 位,无奇偶校验,有 1 个停止位(用 8, N, 1 表示),这是默认的上电复位(Power-on Reset,POR)设置。数据位数、停止位数以及奇偶校验均在 PDSEL<1:0> (UxMODE<2:1>)和STSEL(UxMODE<0>)位中指定。UART 首先发送和接收最低有效位(Least Significant bit,LSb)。 UART 的发送器和接收器在功能上是独立的,但使用相同的数据格式和波特率。

    使能 UART

    通过将ON位(UxMODE<15>)置1来使能UART模块。此外,通过将UTXEN位(UxSTA<10>)和 URXEN 位(UxSTA<12>)置 1 来分别使能 UART 发送器和接收器。一旦将这些使能位置 1,UxTX 和 UxRX 引脚就分别被配置为输出和输入,改写对应 I/O 端口引脚的 TRISx 和 PORTx 寄存器位设置。

    禁止 UART

    通过清零ON位来禁止UART模块。这是任何复位后的默认状态。如果禁止了UART,所有UART引脚在 PORTx 和 TRISx 寄存器中的相应位控制下用作端口引脚。

    禁止 UART 模块会将缓冲区复位为空状态。当禁止模块时,缓冲区中的所有数据都将丢失。

    当禁止 UART 模块时,所有与之相关的错误和状态标志都将复位。 UxSTA 寄存器中的 RXDA、OERR、FERR、PERR、UTXEN、URXEN、UTXBRK 和 UTXBF 位被清零,而 RIDLE 和 TRMT位被置 1。其他控制位(包括 ADDEN、RXISEL<1:0> 和 UTXISEL)以及 UxMODE 和 UxBRG寄存器均不受影响。

    当 UART 模块处于活动状态时,清零 ON 位将中止所有等待的发送和接收,同时如以上所述那样将模块复位。重新使能 UART 将使用同样的配置重新启动 UART 模块。

    4、UART 发送器

    发送器的核心是发送移位寄存器(UxTSR)。UxTSR 从发送FIFO 缓冲区 UxTXREG 中获取数据。通过软件将数据装入 UxTXREG 寄存器。在前一次装入数据的停止位发送之前,不会向 UxTSR 寄存器装入新数据。一旦停止位发送完毕,就会将UxTXREG 寄存器中的新数据 (如果有)装入 UxTSR。

    通过将 UTXEN 使能位 (UxSTA<10>)置 1 来使能发送。实际的发送要到 UxTXREG 寄存器装入了数据并且波特率发生器 UxBRG 产生了移位时钟之后才发生。也可以先装入UxTXREG 寄存器,然后将 UTXEN 使能位置 1 来启动发送。通常,第一次开始发送的时候,由于 UxTSR 寄存器为空,这样传输数据到 UxTXREG 寄存器会导致该数据立即传输到 UxTSR。发送期间清零 UTXEN 位将中止发送并复位发送器。因此, UxTX 引脚将恢复到 UTXINV 位(UxSTA<13>)定义的状态。

    若要选择 9 位发送, PDSEL<1:0> 位 (UxMODE<2:1>)应设置为 11。

    发送缓冲区 (UxTXREG)

    发送缓冲区有 9 位宽和 8 级深。算上发送移位寄存器(UxTSR),用户实际有一个最多 9 级深的缓冲区。当 UxTXREG 的内容被传输到 UxTSR 寄存器时,当前缓冲单元就可以写入新数据。每当缓冲区满时,UTXBF(UxSTA<9>)状态位就会置 1。如果用户试图向已满的缓冲区执行写操作,则新数据将不会被 FIFO 接受。

    FIFO 在任何器件复位时复位,但当器件进入节能模式或从节能模式唤醒时, FIFO 不受影响。

    1 :只有在具有 UART1A、UART1B、UART2A、UART2B、UART3A 和 UART3B 模块的器件中, 8 级深 FIFO 才可用。

    2 :只有在具有 UART1 和 UART2 模块的器件中, 4 级深 FIFO 才可用。

    发送中断

    发送中断标志(UxTXIF)位于相应的中断标志状态(IFS)寄存器中。UTXISEL控制位(UxSTA<15:14>)决定 UART 何时将产生发送中断。当模块第一次使能时, UxTXIF 位被置 1。在工作期间可以在中断模式之间进行切换,但除非缓冲区为空,否则建议不要这么做。

    UxTXIF 标志位指示 UxTXREG 寄存器的状态,而 TRMT 位 (UxSTA<8>)指示 UxTSR 寄存器的状态。 TRMT 状态位是只读位,当 UxTSR 寄存器为空时被置 1。因为没有与该位关联的中断逻辑,所以用户必须查询该位以判断 UxTSR 寄存器是否为空。要清除 UART1 和 UART2 模块的中断,必须在关联的 IFSx 寄存器中,将相应的 UxTXIF 标志位清零。

    对于 UART1A、UART1B、UART2A、UART2B、UART3A 和 UART3B 模块,当 UTXISEL 控制位规定的中断条件为真时,将会产生中断并将标志位置为有效。这意味着要清除这些模块的中断,在清零相应的 UxTXIF 标志之前,用户应用程序必须确保 UTXISEL 控制位规定的中断条件不再为真。

    设置 UART 发送

    1. 对UxBRG寄存器进行初始化,设置合适的波特率。

    2. 通过写入 PDSEL<1:0> (UxMODE<2:1>)和 STSEL (UxMODE<0>)位来设置数据位数、停止位数和奇偶校验选择。

    3. 如果需要发送中断,就要将相应中断允许控制寄存器 (IEC)中的 UxTXIE 控制位置 1。使用相应中断优先级控制(IPC)寄存器中的 UxIP<2:0> 和 UxIS<1:0> 控制位来指定发送中断的中断优先级和子优先级。同时,通过写 UTXISEL(UxSTA<15:14>)位来选择发送中断模式。

    4. 通过将 UTXEN(UxSTA<10>)位置 1 来使能发送,与此同时将 UxTXIF 位置 1。UxTXIF位应在 UART 发送中断服务程序中清零。 UxTXIF 位的操作由 UTXISEL 控制位控制。

    5. 通过将 ON (UxMODE<15>)位置 1 来使能 UART 模块。

    6. 将数据装入UxTXREG寄存器(开始发送)。

    间隔字符的发送

    间隔字符发送包含 1 个启动位,随后的 12 个 0 位和 1 个停止位。在 UxTXREG 寄存器中装入数据时,只要 UART 模块使能并且 UTXBRK 和 UTXEN 位置 1,就会发送帧间隔字符。

    5、UART接收器

    接收器的核心是接收(串行)移位寄存器 (UxRSR)。在 UxRX 引脚上接收数据,并发送到择多检测模块中。在 BRGH = 0 的模式下,择多检测模块以 16 倍波特率的速率工作,并且通过择多检测电路来确定 UxRX 引脚上出现的是高电平还是低电平。在 BRGH = 1 的模式下,择多检测模块以 4 倍波特率的速率工作,并且通过单采样来确定出现的是高电平还是低电平。

    在采样到 UxRX引脚上的停止位之后,UxRSR中接收到的数据被传输到接收FIFO(如果未满)。通过将 URXEN 位 (UxSTA<12>)置 1 来使能接收。

    接收缓冲区 (UxRXREG )

    UART 接收器有一个 9 位宽、最多 8 级深的 FIFO 接收数据缓冲区。UxRXREG 是一个存储器映射的寄存器,可提供对 FIFO 输出的访问。有可能会发生这种情况:FIFO 已满,下一个字开始移入 UxRSR 寄存器,然后发生缓冲区溢出。

    接收器错误处理

    如果 FIFO 已满且新字符已被完全接收到 UxRSR 寄存器中,则溢出错误位 OERR(UxSTA<1>)将被置 1。UxRSR 中的字不会保留,只要 OERR 位置 1,就将禁止继续向接收 FIFO 传输。用户必须用软件清零 OERR 位,以允许继续接收数据。

    若要保存溢出前接收到的数据,用户应先读取所有接收到的字符,然后清零 OERR 位。如果接收到的字符可以丢弃,则用户只要清零 OERR 位即可。这可有效地复位接收 FIFO,同时先前接收到的所有数据都将丢失。

    接收 FIFO 中的数据应在清零 OERR 位之前读出。当 OERR 清零时, FIFO 复位,这将导致缓冲区中的所有数据丢失。

    接收中断

    UART 接收中断标志 (UxRXIF)位于相应的中断标志状态 (IFSx)寄存器中。 RXISEL<1:0>(UxSTA<7:6>)控制位决定 UART 接收器何时产生中断。

    要清除UART1和UART2模块的中断,必须在关联的IFSx寄存器中,将相应的UxRXIF标志清零。

    对于 UART1A、UART1B、UART2A、UART2B、UART3A 和 UART3B 模块,当 RXISEL 控制位规定的中断条件为真时,将会产生中断。这意味着如果要清除这些模块的中断,在清零相应的UxRXIF 标志之前,用户应用程序必须确保 URXISLE 控制位规定的中断条件不再为真。

    RXDA 和 UxRXIF 标志位指示 UxRXREG 寄存器的状态,而 RIDLE 位(UxSTA<4>)指示 UxRSR寄存器的状态。 RIDLE 状态位是只读位,当接收器空闲 (即, UxRSR 寄存器为空)时被置 1。因为没有与该位关联的中断逻辑,所以用户必须查询该位以判断 UxRSR 是否空闲。

    设置UART接收

    请执行以下步骤设置 UART 接收:

    1. 对UxBRG寄存器进行初始化,设置合适的波特率。

    2. 通过写入 PDSEL<1:0> (UxMODE<2:1>)和 STSEL (UxMODE<0>)位来设置数据位数、停止位数和奇偶校验选择。

    3. 如果需要中断,就要将相应中断允许控制 (IEC)寄存器中的 UxRXIE 位置 1。使用相应中断优先级控制(IPC)寄存器中的 UxIP<2:0> 和 UxIS<1:0> 控制位来指定中断的中断优先级和子优先级。同时,通过写入RXISEL<1:0>(UxSTA<7:6>)位来选择接收中断模式。

    4. 通过将 URXEN (UxSTA<12>)位置 1 来使能 UART 接收器。

    5. 通过将 ON (UxMODE<15>)位置 1 来使能 UART 模块。

    6. 接收中断取决于 RXISEL<1:0> 控制位的设置。如果没有允许接收中断,用户可以查询RXDA 位。 UxRXIF 位应在 UART 接收中断服务程序中清零。

    7. 从接收缓冲区中读取数据。如果选择了 9 位发送,则读一个字;否则,读一个字节。每当缓冲区中有数据时, RXDA 状态位 (UxSTA<0>)就会被置 1。

    自动波特率支持

    要允许系统确定所接收字符的波特率,可以使能 ABAUD 位。如果使能了自动波特率检测(ABAUD = 1),则每当接收到启动位时,UART 就会开始自动波特率测量序列。波特率计算采用自平均的方式。该功能仅在禁止自动唤醒(WAKE = 0)时有效。此外,对于自动波特率操作,LPBACK 必须等于0。当 ABAUD位置1时,BRG 计数器值将被清零并开始检测一个启动位;在这种情况下,启动位定义为高电平到低电平跳变后跟随一个低电平到高电平跳变。

    在启动位之后,自动波特率功能需要接收一个 ASCII “U”(55h),以计算相应的比特率。在启动位(上升沿)结束时,BRG 计数器开始使用 F PB /8 时钟计数。在 UxRX 引脚的第 5 个上升沿,统计相应 BRG 总周期数的累计 BRG 计数器值将被传输到 UxBRG 寄存器。ABAUD 位自动清零。

    中断

    UART 能够产生一些中断,反映在数据通信期间发生的事件。它可以产生以下类型的中断:

    • 接收器数据可用中断,通过 UxRXIF 指示。该事件根据RXISEL<1:0>(UxSTA<7:6>)控制位的值而产生。

    • 发送器缓冲区为空中断,通过 UxTXIF 指示。该事件根据UTXISEL<1:0>(UxSTA<15:14>)控制位的值而产生。

    • UART 错误中断,通过 UxEIF 指示。

    - 该事件在发生以下任意错误条件时产生:

    • 检测到奇偶校验错误 PERR (UxSTA<3>)

    • 检测到帧错误 FERR (UxSTA<2>)

    • 发生接收缓冲区溢出条件 OERR (UxSTA<1>)

    所有这些中断标志必须用软件清零。

    UART 器件通过以下相应的 UART 中断允许位使能为中断源:

    • UxRXIE

    • UxTXIE

    • UxEIE

    此外,还必须配置中断优先级位和中断子优先级位:

    • UxIP (IPC6<4:2>)和 UxIS (IPC6<1:0>)

    I/O引脚控制

    通过将 ON 位(UxMODE<15>)、UTXEN 位(UxSTA<10>)和 URXEN 位(UxSTA<12>)置 1使能 UART 模块时, UART 模块将按照 UEN<1:0> (UxMODE<9:8>)位的定义控制 I/O 引脚,改写端口 TRIS 和 LATCH 寄存器位设置。

    UxTX 会被强制设为输出,UxRX 设为输入。此外,如果使能了 UxCTS 和 UxRTS,UxCTS 引脚将被强制设为输入,而 UxRTS/BLCKx 引脚则用作 UxRTS 输出。如果使能了 BLCKx,则UxRTS/BLCKx 输出会驱动 16x 波特率输出。

    节能模式和调试模式下的UART操作

    休眠模式下的操作

    当器件进入Sleep(休眠)模式时,系统时钟被禁止。 UART 在 Sleep (休眠)模式下不工作。如果在发送过程中进入 Sleep (休眠)模式,则发送会被中止, UxTX 引脚被驱动为逻辑 1。类似地,如果在接收过程中进入 Sleep(休眠)模式,接收会被中止。RTS 和 BCLK 引脚会被驱动为 0。

    (可选) UART 模块可用于在检测到启动位时将 PIC32MX 器件从 Sleep (休眠)模式唤醒。如果 WAKE 位 (UxMODE<7>)在器件进入 Sleep (休眠)模式之前置 1,并且允许 UART 接收中断(UxRXIE = 1),则 UxRX 引脚上的下降沿会产生接收中断并唤醒器件。接收中断选择模式位 (RXISEL)对该功能没有影响。只有 ON (UxMODE<15>)位置 1 时,才会产生唤醒中断。

    空闲模式下的操作

    当器件进入 Idle (空闲)模式时,系统时钟源保持工作,但 CPU 停止执行代码。 SIDL 位(UxMODE<13>)用于选择在器件进入 Idle(空闲)模式时,UART 模块是停止工作还是继续正常工作。

    • 如果 SIDL = 1,则模块在 Idle(空闲)模式下停止工作。模块在 Idle(空闲)模式下停止工作时 (SIDL = 1)执行与在 Sleep (休眠)模式下相同的过程。

    • 如果 SIDL = 0,则模块在 Idle (空闲)模式下继续工作。

    调试模式下的操作

    FRZ 位(UxMODE<14>)决定 CPU 在 Debug(调试)模式下执行调试异常代码(即,应用程序暂停)时, UART 模块是继续运行还是停止。具体地说, FRZ 位会以以下形式影响操作:

    • 当 FRZ = 1 且应用程序在 Debug (调试)模式下暂停时,模块会冻结其操作,并且不会更改 UART 模块的状态。在应用程序继续开始执行代码之后,模块将继续工作。

    • 如果 FRZ = 0,则在 Debug (调试)模式下,即使应用程序暂停,模块也会继续工作。

    各种复位的影响

    器件复位:在发生器件复位时,所有 UART 寄存器会被强制设为它们的复位状态。

    上电复位:在发生上电复位 (POR)时,所有 UART 寄存器会被强制设为它们的复位状态。

    看门狗复位:在发生看门狗复位时,所有 UART 寄存器保持不变。

    6、使用Harmony配置串口收发

    1、在Available Components组件中将UART1添加到Project Graph中;

     2、组件添加后,组件初始内容如下;

    3、组件配置完成后点击左侧的Generate Code按钮生成代码;

    4、生成的代码与原始代码存在差异,需进行确认;

    5、代码生成后需要的操作;

            1、系统初始化完成后添加串口初始化函数初始化串口;

            2、添加数据发送及接收函数;

    6、编译运行将代码烧录到开发板中;

    点击编译按钮,编译提示BUILD SUCCESSFUL,点击烧录,提示Programming/Verify complete,使用USB转串口工具,在电脑上可以看到开发板发送的数据。

    串口配置说明

    Operating Mode: 运行模式

    Blocking mode 阻塞模式

    Non-blocking mode 非阻塞模式

    Ring buffer mode 环形缓冲模式

    Stop Selection bit停止位选择,可选为1位停止位或2位停止位;

    Parity and Data Selection bits 奇偶校验和数据选择位

    可选9位数据位无奇偶校验、8位数据位奇校验、8位数据位偶校验、8位数据位无校验

     

    UARTx Enable bits UART使能位

    UxTX, UxRX and UxBCLK pins are enabled and used; UxCTS is controlled by corresponding bits in the PORTx register 使能并使用 UxTX、 UxRX 和 UxBCLK 引脚; UxCTS 引脚由 PORTx 寄存器中的相应位控制

    UxTX, UxRX , UxCTS and UxRTS pins are enabled and used 使能并使用 UxTX、 UxRX、 UxCTS 和 UxRTS 引脚

    UxTX ,UxRX and UxRTS pins are enabled and used; UxCTS is controlled by corresponding bits in the PORTx register 使能并使用 UxTX、 UxRX 和 UxRTS 引脚; UxCTS 引脚由 PORTx 寄存器中的相应位控制

    UxTX and UxRX pins are enabled and used; UxCTS and UxRTS/UxBCLK pins are controlled by corresponding bits in the PORTx register使能并使用UxTX和UxRX引脚;UxCTS和UxRTS/UxBCLK引脚由PORTx寄存器中的相应位控制

    UxCTS(允许发送)和 UxRTS(请求发送)可以工作于单工和流控模式,控制数据终端设备之间的发送和接收。BCLKx用于支持外部IrDA编解码器。

    Clock Frequency为串口时钟频率

    Baud Rate为串口波特率

    7、实际代码分析

    文件plib_uart1.c中

    //清除故障标志位
    void static UART1_ErrorClear( void )
    {
        UART_ERROR errors = UART_ERROR_NONE;
        uint8_t dummyData = 0u;
    
        errors = (UART_ERROR)(U1STA & (_U1STA_OERR_MASK | _U1STA_FERR_MASK | _U1STA_PERR_MASK));
    
        if(errors != UART_ERROR_NONE) //存在故障
        {
            /* If it's a overrun error then clear it to flush FIFO */
            if(U1STA & _U1STA_OERR_MASK) //数据溢出错误
            {
                U1STACLR = _U1STA_OERR_MASK;
            }
    
            /* Read existing error bytes from FIFO to clear parity and framing error flags */
            while(U1STA & _U1STA_URXDA_MASK) //清空FIFO的数据
            {
                dummyData = U1RXREG;
            }
    
            /* Clear error interrupt flag */
            IFS0CLR = _IFS0_U1EIF_MASK; //错误中断
    
            /* Clear up the receive interrupt flag so that RX interrupt is not triggered for error bytes */
            IFS0CLR = _IFS0_U1RXIF_MASK; //接收中断
        }
    
        // Ignore the warning
        (void)dummyData;
    }
    
    //串口1初始化
    void UART1_Initialize( void )
    {
        /* Set up UxMODE bits */
        /* STSEL  = 0 */ //停止位选择0:1位;1:2位
        /* PDSEL = 0 */ //奇偶位数据位选择00:8位数据位无奇偶校验;01:8位数据位偶校验;10:8位数据位奇校验;11:9位数据位无奇偶校验;
        /* UEN = 0 */ //UART使能位
        U1MODE = 0x8; //bit3 高速模式
    
        /* Enable UART1 Receiver and Transmitter */
        U1STASET = (_U1STA_UTXEN_MASK | _U1STA_URXEN_MASK | _U1STA_UTXISEL1_MASK ); //发送器使能  接收器使能  发送中断模式选择
    
        /* BAUD Rate register Setup */
        U1BRG = 173; //波特率分频比  波特率=串口时钟频率/[4*(波特率分频率比+1)] 高速模式下为4,标准速度模式下为16
    
        /* Disable Interrupts */
        IEC0CLR = _IEC0_U1EIE_MASK; //错误中断允许控制位
        IEC0CLR = _IEC0_U1RXIE_MASK; //接收中断允许控制位
        IEC0CLR = _IEC0_U1TXIE_MASK; //发送中断允许控制位
    
        /* Initialize instance object */
        uart1Obj.rxBuffer = NULL;
        uart1Obj.rxSize = 0;
        uart1Obj.rxProcessedSize = 0;
        uart1Obj.rxBusyStatus = false;
        uart1Obj.rxCallback = NULL;
        uart1Obj.txBuffer = NULL;
        uart1Obj.txSize = 0;
        uart1Obj.txProcessedSize = 0;
        uart1Obj.txBusyStatus = false;
        uart1Obj.txCallback = NULL;
        uart1Obj.errors = UART_ERROR_NONE;
    
        /* Turn ON UART1 */
        U1MODESET = _U1MODE_ON_MASK; //UART使能
    }
    
    //串口设置
    bool UART1_SerialSetup( UART_SERIAL_SETUP *setup, uint32_t srcClkFreq )
    {
        bool status = false;
        uint32_t baud;
        int32_t brgValHigh = 0;
        int32_t brgValLow = 0;
        uint32_t brgVal = 0;
        uint32_t uartMode;
    
        if((uart1Obj.rxBusyStatus == true) || (uart1Obj.txBusyStatus == true))
        {
            /* Transaction is in progress, so return without updating settings */
            return status;
        }
    
        if (setup != NULL)
        {
            baud = setup->baudRate;
    
            if (baud == 0)
            {
                return status; //波特率位0返回错误
            }
    
            if(srcClkFreq == 0)
            {
                srcClkFreq = UART1_FrequencyGet(); //获取时钟频率
            }
    
            /* Calculate BRG value */
            brgValLow = (((srcClkFreq >> 4) + (baud >> 1)) / baud ) - 1; //波特率分频比=串口时钟/(速度模式*波特率)-1
            brgValHigh = (((srcClkFreq >> 2) + (baud >> 1)) / baud ) - 1;
    
            /* Check if the baud value can be set with low baud settings */
            if((brgValLow >= 0) && (brgValLow <= UINT16_MAX))
            {
                brgVal =  brgValLow;
                U1MODECLR = _U1MODE_BRGH_MASK;
            }
            else if ((brgValHigh >= 0) && (brgValHigh <= UINT16_MAX))
            {
                brgVal = brgValHigh;
                U1MODESET = _U1MODE_BRGH_MASK;
            }
            else
            {
                return status;
            }
    
            if(setup->dataWidth == UART_DATA_9_BIT) //9位数据宽度
            {
                if(setup->parity != UART_PARITY_NONE)
                {
                   return status;
                }
                else //9位数据模式无奇偶校验
                {
                   /* Configure UART1 mode */
                   uartMode = U1MODE;
                   uartMode &= ~_U1MODE_PDSEL_MASK; //奇偶校验和数据选择位
                   U1MODE = uartMode | setup->dataWidth;
                }
            }
            else //8位数据宽度
            {
                /* Configure UART1 mode */
                uartMode = U1MODE;
                uartMode &= ~_U1MODE_PDSEL_MASK; //奇偶校验和数据选择位UxMODE<1:0>
                U1MODE = uartMode | setup->parity ;
            }
    
            /* Configure UART1 mode */
            uartMode = U1MODE;
            uartMode &= ~_U1MODE_STSEL_MASK; //停止位UxMODE<0>
            U1MODE = uartMode | setup->stopBits ;
    
            /* Configure UART1 Baud Rate */
            U1BRG = brgVal; //波特率分频比位UxBRG<15:0
            status = true;
        }
        return status;
    }
    
    //自动波特率查询
    bool UART1_AutoBaudQuery( void )
    {
        if(U1MODE & _U1MODE_ABAUD_MASK) //自动波特率使能位
            return true;
        else
            return false;
    }
    
    //自动波特率设置
    void UART1_AutoBaudSet( bool enable )
    {
        if( enable == true )
        {
            U1MODESET = _U1MODE_ABAUD_MASK; //自动波特率使能位
        }
    
        /* Turning off ABAUD if it was on can lead to unpredictable behavior, so that direction of control is not allowed in this function. */
    }
    
    //串口1数据读取
    bool UART1_Read(void* buffer, const size_t size )
    {
        bool status = false;
        uint8_t* lBuffer = (uint8_t* )buffer;
    
        if(lBuffer != NULL)
        {
            /* Check if receive request is in progress */
            if(uart1Obj.rxBusyStatus == false)
            {
                /* Clear error flags and flush out error data that may have been received when no active request was pending */
                UART1_ErrorClear();
    
                uart1Obj.rxBuffer = lBuffer;
                uart1Obj.rxSize = size;
                uart1Obj.rxProcessedSize = 0;
                uart1Obj.rxBusyStatus = true;
                uart1Obj.errors = UART_ERROR_NONE;
    
                status = true;
    
                /* Enable UART1_FAULT Interrupt */
                IEC0SET = _IEC0_U1EIE_MASK; //错误中断允许控制位
    
                /* Enable UART1_RX Interrupt */
                IEC0SET = _IEC0_U1RXIE_MASK; //接收中断允许控制位
            }
        }
        return status;
    }
    
    //串口1数据写入
    bool UART1_Write( void* buffer, const size_t size )
    {
        bool status = false;
        uint8_t* lBuffer = (uint8_t*)buffer;
    
        if(lBuffer != NULL)
        {
            /* Check if transmit request is in progress */
            if(uart1Obj.txBusyStatus == false)
            {
                uart1Obj.txBuffer = lBuffer;
                uart1Obj.txSize = size;
                uart1Obj.txProcessedSize = 0;
                uart1Obj.txBusyStatus = true;
                status = true;
    
                /* Initiate the transfer by writing as many bytes as we can */
                while((!(U1STA & _U1STA_UTXBF_MASK)) && (uart1Obj.txSize > uart1Obj.txProcessedSize) ) //发送缓冲区满
                {
                    if (( U1MODE & (_U1MODE_PDSEL0_MASK | _U1MODE_PDSEL1_MASK)) == (_U1MODE_PDSEL0_MASK | _U1MODE_PDSEL1_MASK)) //奇偶校验和数据选择位
                    {
                        /* 9-bit mode */
                        U1TXREG = ((uint16_t*)uart1Obj.txBuffer)[uart1Obj.txProcessedSize++];
                    }
                    else
                    {
                        /* 8-bit mode */
                        U1TXREG = uart1Obj.txBuffer[uart1Obj.txProcessedSize++];
                    }
                }
                IEC0SET = _IEC0_U1TXIE_MASK;
            }
        }
        return status;
    }
    
    //读取故障
    UART_ERROR UART1_ErrorGet( void )
    {
        UART_ERROR errors = uart1Obj.errors;
    
        uart1Obj.errors = UART_ERROR_NONE;
    
        /* All errors are cleared, but send the previous error state */
        return errors;
    }
    
    //
    void UART1_ReadCallbackRegister( UART_CALLBACK callback, uintptr_t context )
    {
        uart1Obj.rxCallback = callback;
    
        uart1Obj.rxContext = context;
    }
    
    //查询串口发送忙状态
    bool UART1_ReadIsBusy( void )
    {
        return uart1Obj.rxBusyStatus;
    }
    
    //获取接收计数
    size_t UART1_ReadCountGet( void )
    {
        return uart1Obj.rxProcessedSize;
    }
    
    //串口读取中止
    bool UART1_ReadAbort(void)
    {
        if (uart1Obj.rxBusyStatus == true)
        {
            /* Disable the fault interrupt */
            IEC0CLR = _IEC0_U1EIE_MASK; //错误中断允许控制位
    
            /* Disable the receive interrupt */
            IEC0CLR = _IEC0_U1RXIE_MASK; //接收中断允许控制位
    
            uart1Obj.rxBusyStatus = false;
    
            /* If required application should read the num bytes processed prior to calling the read abort API */
            uart1Obj.rxSize = uart1Obj.rxProcessedSize = 0;
        }
    
        return true;
    }
    
    //
    void UART1_WriteCallbackRegister( UART_CALLBACK callback, uintptr_t context )
    {
        uart1Obj.txCallback = callback;
    
        uart1Obj.txContext = context;
    }
    
    //获取串口写入忙状态
    bool UART1_WriteIsBusy( void )
    {
        return uart1Obj.txBusyStatus;
    }
    
    //获取发送计数
    size_t UART1_WriteCountGet( void )
    {
        return uart1Obj.txProcessedSize;
    }
    
    //串口错误中断服务函数
    static void UART1_FAULT_InterruptHandler (void)
    {
        /* Save the error to be reported later */
        uart1Obj.errors = (UART_ERROR)(U1STA & (_U1STA_OERR_MASK | _U1STA_FERR_MASK | _U1STA_PERR_MASK)); //接收缓冲区溢出错误状态位 帧错误状态位(只读) 奇偶校验错误状态位 (只读)
    
        /* Disable the fault interrupt */
        IEC0CLR = _IEC0_U1EIE_MASK; //错误中断允许控制位
    
        /* Disable the receive interrupt */
        IEC0CLR = _IEC0_U1RXIE_MASK; //接收中断允许控制位
    
        /* Clear rx status */
        uart1Obj.rxBusyStatus = false;
    
        UART1_ErrorClear();
    
        /* Client must call UARTx_ErrorGet() function to get the errors */
        if( uart1Obj.rxCallback != NULL )
        {
            uart1Obj.rxCallback(uart1Obj.rxContext);
        }
    }
    
    //串口接收中断服务函数
    static void UART1_RX_InterruptHandler (void)
    {
        if(uart1Obj.rxBusyStatus == true)
        {
            while((_U1STA_URXDA_MASK == (U1STA & _U1STA_URXDA_MASK)) && (uart1Obj.rxSize > uart1Obj.rxProcessedSize) ) //接收缓冲区数据存在标志位(只读)
            {
                if (( U1MODE & (_U1MODE_PDSEL0_MASK | _U1MODE_PDSEL1_MASK)) == (_U1MODE_PDSEL0_MASK | _U1MODE_PDSEL1_MASK))
                {
                    /* 9-bit mode */
                    ((uint16_t*)uart1Obj.rxBuffer)[uart1Obj.rxProcessedSize++] = (uint16_t )(U1RXREG);
                }
                else
                {
                    /* 8-bit mode */
                    uart1Obj.rxBuffer[uart1Obj.rxProcessedSize++] = (uint8_t )(U1RXREG);
                }
            }
    
            /* Clear UART1 RX Interrupt flag */
            IFS0CLR = _IFS0_U1RXIF_MASK; //接收中断标志状态位
    
            /* Check if the buffer is done */
            if(uart1Obj.rxProcessedSize >= uart1Obj.rxSize)
            {
                uart1Obj.rxBusyStatus = false;
    
                /* Disable the fault interrupt */
                IEC0CLR = _IEC0_U1EIE_MASK; //错误中断允许控制位
    
                /* Disable the receive interrupt */
                IEC0CLR = _IEC0_U1RXIE_MASK; //接收中断允许控制位
    
    
                if(uart1Obj.rxCallback != NULL)
                {
                    uart1Obj.rxCallback(uart1Obj.rxContext);
                }
            }
        }
        else
        {
            // Nothing to process
            ;
        }
    }
    
    //串口发送中断服务函数
    static void UART1_TX_InterruptHandler (void)
    {
        if(uart1Obj.txBusyStatus == true)
        {
            while((!(U1STA & _U1STA_UTXBF_MASK)) && (uart1Obj.txSize > uart1Obj.txProcessedSize) ) //发送缓冲区满状态位(只读)
            {
                if (( U1MODE & (_U1MODE_PDSEL0_MASK | _U1MODE_PDSEL1_MASK)) == (_U1MODE_PDSEL0_MASK | _U1MODE_PDSEL1_MASK))
                {
                    /* 9-bit mode */
                    U1TXREG = ((uint16_t*)uart1Obj.txBuffer)[uart1Obj.txProcessedSize++];
                }
                else
                {
                    /* 8-bit mode */
                    U1TXREG = uart1Obj.txBuffer[uart1Obj.txProcessedSize++];
                }
            }
    
            /* Clear UART1TX Interrupt flag */
            IFS0CLR = _IFS0_U1TXIF_MASK;
    
            /* Check if the buffer is done */
            if(uart1Obj.txProcessedSize >= uart1Obj.txSize)
            {
                uart1Obj.txBusyStatus = false;
    
                /* Disable the transmit interrupt, to avoid calling ISR continuously */
                IEC0CLR = _IEC0_U1TXIE_MASK; //发送中断标志状态位
    
                if(uart1Obj.txCallback != NULL)
                {
                    uart1Obj.txCallback(uart1Obj.txContext);
                }
            }
        }
        else
        {
            // Nothing to process
            ;
        }
    }
    
    //串口服务函数
    void UART_1_InterruptHandler (void)
    {
        /* Call Error handler if Error interrupt flag is set */
        if ((IFS0 & _IFS0_U1EIF_MASK) && (IEC0 & _IEC0_U1EIE_MASK))
        {
            UART1_FAULT_InterruptHandler();
        }
        /* Call RX handler if RX interrupt flag is set */
        if ((IFS0 & _IFS0_U1RXIF_MASK) && (IEC0 & _IEC0_U1RXIE_MASK))
        {
            UART1_RX_InterruptHandler();
        }
        /* Call TX handler if TX interrupt flag is set */
        if ((IFS0 & _IFS0_U1TXIF_MASK) && (IEC0 & _IEC0_U1TXIE_MASK))
        {
            UART1_TX_InterruptHandler();
        }
    }

    8、实验验证

    点击编译按钮,编译提示BUILD SUCCESSFUL,点击烧录,提示Programming/Verify complete,

    使用USB转串口工具,在电脑上可以看到开发板发送的数据。

    时间:2021.08.08

    展开全文
  • PIC单片机学习—USART串口

    千次阅读 2020-11-27 11:23:13
    最近做了几个项目都用到了PIC单片机,在这几个项目之前我只用到了51单片机和STM32来做控制类的项目,用PIC单片机的时候发现使用的时候和51单片机还是有所区别,有许多小坑需要注意,所以决定写几篇针对新手使用PIC...

    PIC单片机学习—USART串口

    最近做了几个项目都用到了PIC单片机,在这几个项目之前我只用到了51单片机和STM32来做控制类的项目,用PIC单片机的时候发现使用的时候和51单片机还是有所区别,有许多小坑需要注意,所以决定写几篇针对新手使用PIC单片机时可以参考学习的文章。


    前言

    串口是使用频率非常高的通信接口,掌握串口是单片机项目必须技能


    一、USART串口是什么?

    USART:(Universal Synchronous/Asynchronous Receiver/Transmitter),通用同步/异步串行接收/发送器。
    通用同步 / 异步收发器 (USART) 模块是两个串行 I/O 模块之一 , USART也称为串行通信接口或 SCI。
    USART 可以配置为全双工异步系统,可与计算机等外设进行通信;也可配置为半双工同步系统,可与 A/D 或 D/A 集成电路,以及串行 EEPROM等外设器件进行通信。


    二、PIC单片机USART串口配置要点

    1.与串口相关寄存器

    TXSTA:发送状态和控制寄存器
    TXSTA:发送状态和控制寄存器
    TXSTA寄存器解释RCSTA:接收状态和控制寄存器
    RCSTA:接收状态和控制寄存器接收寄存器解释

    2.异步模式配置步骤

    我们使用串口一般都使用异步模式,下面简单介绍异步配置步骤:
    1.初始化SPBRGH和SPBRGL寄存器对以及BRGH和BRG16位,获得所需的波特率。
    2.清零RX引脚的ANSEL位(如适用)。
    3.将SPEN位置1使能串口。SYNC位必须清零才能进行异步操作。
    4.如果需要中断,将PIE1寄存器的RCIE位以及INTCON寄存器的GIE和PEIE位置1。
    5.如果需要接收9位数据,将RX9位置1。
    6.将CREN位置1使能接收。
    7.当字符从RSR被移入接收缓冲区时,RCIF中断标志位将被置1。如果RCIE中断允许位也置1,则产生中断。
    8.读取RCSTA寄存器取得错误标志和第9个数据位(9位数据接收使能时)。
    9.读取RCREG寄存器从接收缓冲区取得接收数据的低8位。
    10.发生溢出时,通过清零CREN接收器使能位清零OERR标志位。


    三、容易“踩坑”点

    以下是我在实际使用中碰到的一些小问题,这几次都是调试了半天,最后猛的发现原来是这个问题,大家只要注意了就可以避免,望大家参考。

    1、IO口配置必须正确

    PIC单片机的串口一般都是与通用IO口复用,当启用串口功能时,一部分PIC单片机只要使能了串口收发功能,就会自动配置好TX及RX相关端口,不论TRIS三态寄存器相关为配置是输入或输出,TX及RX都可正常使用。但是PIC16LF1823的RX端口必须配置TRIS相关位为输入。
    另外PIC的串口经常会和模拟口复用,这里必须要配置为数字口,否则会一直读为0.
    总结,使用串口时,相关IO口必须配置为数字模式,同时TX配置为输出模式,RX配置为输入模式,这样的话,不论在哪种型号的单片机上都可以正常使用,就不会出现预期外的问题。

    2、电压与晶振频率相匹配

    使用PIC单片机时必须要注意单片机工作在不同的电压时,所能使用的晶振频率是有区别的,大家一定要注意查看相对应芯片数据手册,一般是在电气规范章节中。不过电压和频率配置不对,单片机无法正常工作。比如,下面PIC1LF886的电压与频率关系图。
    PIC16F883/884/886/887 电压—频率关系图从上面的电压-频率关系图,我们可以看出,当PIC16F886使用3.3V电压时,如果配上12MHz晶振,单片机是无法正常工作的。

    展开全文
  • 调试通过的PIC串口模拟程序,用于没有串口的单片机上
  • PIC18F65K40 PIC18F66K40 PIC18F67K40 多usart 串口初始化以及发送代码 K40系列 发送字符串有IC 硬件BUG 请查看官方的勘误手册
  • I2C PIC16F15345,EEPROM 3 Click,串行接口 远程存储库: :
  • 串口实验成功,发送成功返回发送数据,采用PIC16F690单片机,由于PIC 资源少,希望对大家有所帮助
  • PIC18F452串口通信程序

    2014-12-19 20:41:58
    用C语言写的PIC18F452的串口通信代码,方便各位学习USART通信,需要的同学抓紧了,代码已测试通过。
  • PIC16F1946 串口通信程序

    热门讨论 2013-04-03 15:25:18
    本资源包含一个基于pic16f1946的简单的串口通信工程。当串口收到一串数据后,蜂鸣器发出声响一声。同时将收到的数据发送出来。
  • PIC 单片机遇到的串口接收问题

    千次阅读 2018-05-15 10:05:25
    在使用PIC16F1825/9芯片的串口接收时遇到一个问题,就是当串口快速接收时容易出现串口假死的现象,也就是程序运行正常,串口发送也是正常的,但是串口就是不能接收数据。经查询PIC数据手册发现: PIC数据快速接收...

    在使用PIC16F1825/9芯片的串口接收时遇到一个问题,就是当串口快速接收时容易出现串口假死的现象,也就是程序运行正常,串口发送也是正常的,但是串口就是不能接收数据。经查询PIC数据手册发现:
    PIC数据快速接收但是又未及时处理的情况下,容易出现接收溢出错误。

    PIC数据手册截图

    展开全文
  • PIC18F25K80串口自发自收

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,245
精华内容 1,698
关键字:

pic串口