作为一名使用PIC单片机近三十年的工程师,我最早从PIC16F87X系列起步,逐步深入至更集成、功能更丰富的型号。在智慧农业、工业控制等实际项目中,PIC32MX是我频繁使用的核心芯片。其丰富的外设与六串口设计,非常适合构建多通道通信与控制系统。本次我将以一款实际投产数年的核心控制板为例,控制板MCU型号为PIC32MX534F064H,详解其六串口架构与不同波特率灵活配置的实现方法。

该控制板集成了以下6大功能:

12RS485数据收发(可接LED屏、各种传感器、或与其他控制板通信)

21UART-TTL(可接摄像头等);

314G模块数据收发(移远或中移4G模块);

41LORA无线数据收发或RS485数据收发;

52路无源开关量输入;

6、太阳能供电(带充电管理)或直流电源直接供电;

一、硬件设计:串口电路详解

PIC32MX534F064H具备六个独立UART模块,本设计中:

  • UART1 可通过跳线切换为LORA无线或RS485有线通信,增强系统灵活性。
  • UART2 通过电平转换电路连接4G模块,实现无线远程通信。
  • UART3UART6RS485有线通信,可接LED屏、触摸屏、各种传感器等。
  • UART4 UART-TTL,可接摄像头等。
  • UART5 在本控制板上没有使用。

UART1UART2可以设置为中断接收数据,UART3- UART6只能是查询接收数据。

RS485接口电路

二、串口例程:

PIC单片机输入输出寄存器的控制字设置与其他如MSP430系列单片机不一样,一般其他系列单片机某一I/O口输出置1、输入置0PIC则相反,输出置0、输入置1,你可以把0想成O(对应OUT),把1想成I(对应IN),这样会不容易设置错。

以下是串口示例(80M主频),串口1波特率9600,串口2波特率115200,串口346波特率都是9600,都是8N1格式,数据在不同串口间可透传,具体配置及程序如下:

#include<p32mx534f064h.h>

#pragma config FPLLMUL=MUL_20,FPLLIDIV=DIV_2,FPLLODIV=DIV_1,FWDTEN=OFF
#pragma config POSCMOD=HS,FNOSC=PRIPLL,FPBDIV=DIV_1

#define SYS_FREQ                          (80000000L)
unsigned char dres_485=1, flag_rev=0,flag_rev2=0,flag_rev3,flag_rev4,flag_rev5,flag_rev6;
unsigned int  time_tnt,time_tnt2,time_tnt3,time_tnt4,time_tnt5,time_tnt6, ,rev_rnt=0,rev_rnt2=0,rev_rnt3,rev_rnt4,rev_rnt5,rev_rnt6,tran_rnt1=0,tran_rnt2=0,tran_rnt3,tran_rnt4,tran_rnt5,tran_rnt6;

unsigned char trans[200];
unsigned char reciv[200];
unsigned char trans2[200];
unsigned char reciv2[200];
unsigned char trans3[200];
unsigned char reciv3[200];
unsigned char trans4[200];
unsigned char reciv4[200];
unsigned char trans5[200];
unsigned char reciv5[200];
unsigned char trans6[200];
unsigned char reciv6[200];
void delay(unsigned int a)
               {
               int i,j;
               for(i=0;i<a;i++)
                               for(j=0;j<100;j++)
                                              ;
               }
void uart_send1(unsigned char dat) //串口1发送数据
{
               U1STAbits.UTXEN=1;
               U1TXREG=dat;
               while(!U1STAbits.TRMT);
}
void uart_send2(unsigned char dat) //串口2发送数据
{
               U2STAbits.UTXEN=1;
               U2TXREG=dat;
               while(!U2STAbits.TRMT);
}
void uart_send3(unsigned char dat)
{
               U3STAbits.UTXEN=1;
               U3TXREG=dat;
               while(!U3STAbits.TRMT);
}
void uart_send4(unsigned char dat)
{
               U4STAbits.UTXEN=1;
               U4TXREG=dat;
               while(!U4STAbits.TRMT);
}
void uart_send5(unsigned char dat)
{
               U5STAbits.UTXEN=1;
               U5TXREG=dat;
               while(!U5STAbits.TRMT);
}
void uart_send6(unsigned char dat)
{
               U6STAbits.UTXEN=1;
               U6TXREG=dat;
               while(!U6STAbits.TRMT);
}
void main() {
    unsigned int i,j; 
                               AD1PCFG=0XFFFF;
                               
                               TRISB=0x0180;
               
                               PORTB=0x0000;
                               TRISC=0;
                               PORTC=0x0000;
                               TRISD=0x0204;
                               PORTD=0x0000;
                               TRISE=0x0000;
                               PORTE=0x0000;
                               TRISF=0x0010;
                               PORTF=0x0000;
                               TRISG=0x0280;
                               PORTG=0x0000;
                               DDPCON = 0x00 ;  //关闭EJTAG口,
                               OSCCON&=0xfffd;
SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
ConfigIntTimer1(T1_INT_ON | T1_INT_PRIOR_5 | T1_INT_SUB_PRIOR_1);
INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR);
UARTSetLineControl(UART1, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
                           UARTConfigure(UART1, UART_ENABLE_HIGH_SPEED|UART_ENABLE_PINS_TX_RX_ONLY);
                           UARTSetDataRate(UART1, SYS_FREQ,9600);
                           UARTSetFifoMode(UART1, UART_INTERRUPT_ON_RX_NOT_EMPTY);

                           ConfigIntUART1(UART_RX_INT_EN | UART_INT_PR6 | UART_INT_SUB_PR2);
                           EnableIntU1RX;
                           UARTEnable(UART1, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

                           UARTSetLineControl(UART2, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
                           UARTConfigure(UART2, UART_ENABLE_HIGH_SPEED|UART_ENABLE_PINS_TX_RX_ONLY);
                           UARTSetDataRate(UART2, SYS_FREQ, 115200);
                           UARTSetFifoMode(UART2, UART_INTERRUPT_ON_RX_NOT_EMPTY);

                           ConfigIntUART2(UART_RX_INT_EN | UART_INT_PR6 | UART_INT_SUB_PR2);
                           EnableIntU2RX;
                           UARTEnable(UART2, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

                           UARTSetLineControl(UART3, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
                           UARTConfigure(UART3, UART_ENABLE_HIGH_SPEED|UART_ENABLE_PINS_TX_RX_ONLY);
                           UARTSetDataRate(UART3, SYS_FREQ, 9600);
                           UARTSetFifoMode(UART3, UART_INTERRUPT_ON_RX_NOT_EMPTY);

                           UARTEnable(UART3, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

                           UARTSetLineControl(UART4, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
                           UARTConfigure(UART4, UART_ENABLE_HIGH_SPEED|UART_ENABLE_PINS_TX_RX_ONLY);
                           UARTSetDataRate(UART4, SYS_FREQ, 9600);
                           UARTSetFifoMode(UART4, UART_INTERRUPT_ON_RX_NOT_EMPTY);

                           UARTEnable(UART4, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

                           UARTSetLineControl(UART5, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
                           UARTConfigure(UART5, UART_ENABLE_HIGH_SPEED|UART_ENABLE_PINS_TX_RX_ONLY);
                           UARTSetDataRate(UART5, SYS_FREQ, 115200);
                           UARTSetFifoMode(UART5, UART_INTERRUPT_ON_RX_NOT_EMPTY);

                           UARTEnable(UART5, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));

                           UARTSetLineControl(UART6, UART_DATA_SIZE_8_BITS | UART_PARITY_NONE | UART_STOP_BITS_1);
                           UARTConfigure(UART6, UART_ENABLE_HIGH_SPEED|UART_ENABLE_PINS_TX_RX_ONLY);
                           UARTSetDataRate(UART6, SYS_FREQ, 9600);
                           UARTSetFifoMode(UART6, UART_INTERRUPT_ON_RX_NOT_EMPTY);

                           UARTEnable(UART6, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_RX | UART_TX));
//其他初始化
INTEnableInterrupts();
                           OpenTimer1(T1_ON | T1_PS_1_1 | T1_SOURCE_INT,4000); //分频设置为1
delay(10000);
while(1) {
if(U3STAbits.URXDA)
                                          {
                                                         reciv3[rev_rnt3]=UARTGetDataByte(UART3);
                                                         
                                                         rev_rnt3+=1;
                                                         time_tnt3=0;
                                                         flag_rev3=1;
                                          } 
                                          if(U4STAbits.URXDA)
                                          {
                                                         reciv4[rev_rnt4]=UARTGetDataByte(UART4);
                                                         
                                                         rev_rnt4+=1;
                                                         time_tnt4=0;
                                                         flag_rev4=1;
                                          } 
                                          if(U5STAbits.URXDA)
                                          {
                                                         reciv5[rev_rnt5]=tmp3=UARTGetDataByte(UART5);
                                                         
                                                         rev_rnt5+=1;
                                                         time_tnt5=0;
                                                         flag_rev5=1;
                                          }
                                          if(U6STAbits.URXDA)
                                          {
                                                         reciv6[rev_rnt6]=UARTGetDataByte(UART6);
                                                         
                                                         rev_rnt6+=1;
                                                         time_tnt6=0;
                                                         flag_rev6=1;
                                          }
        // 主循环,可加入其他任务
    }
}

void __ISR(_UART1_VECTOR, IPL6SOFT) IntUart1Handler(void)
{
 
  if (INTGetFlag(INT_SOURCE_UART_RX(UART1)))
    {
     
             reciv[rev_rnt]=UARTGetDataByte(UART1);
             
             
                     rev_rnt+=1;
                     time_tnt=0;
                     flag_rev=1;
             
                           
    } 
      INTClearFlag(INT_SOURCE_UART_RX(UART1));
     
}
void __ISR(_UART2_VECTOR, IPL6SOFT) IntUart2Handler(void)
{
 
  if (INTGetFlag(INT_SOURCE_UART_RX(UART2)))
    {
     
              reciv2[rev_rnt2]=tmp2=UARTGetDataByte(UART2);
             
                            rev_rnt2+=1;
                            time_tnt2=0;
                            flag_rev2=1;
    } 
      INTClearFlag(INT_SOURCE_UART_RX(UART2));
     
}
void __ISR(_TIMER_1_VECTOR, ipl5) _Timer1Handler(void)
{
 //      DisableIntT1;
             
              if(flag_rev==1)
              {
                     time_tnt+=1;  //1570约为06ms
              }
              if(flag_rev2==1)
              {
                     time_tnt2+=1;  //1570约为06ms
              }
              if(flag_rev3==1)
              {
                     time_tnt3+=1;  //1570约为06ms
              }
              if(flag_rev4==1)
              {
                     time_tnt4+=1;  //1570约为06ms
              }
              if(flag_rev5==1)
              {
                     time_tnt5+=1;  //1570约为06ms
              }
              if(flag_rev6==1)
              {
                     time_tnt6+=1;  //1570约为06ms
              }
             
              INTClearFlag(INT_T1);//中断标志清零
 
//       EnableIntT1;
}三、本系列文章规划

本文是《PIC单片机高阶实战》系列的第一篇,后续将逐步展开以下内容:

序号

主题

内容概要

1

振荡器与定时器

时钟配置与定时中断

2

UART通信

串口配置、波特率转换、数据透传

3

I/O按键输入

电平变化中断

4

4G模块数据收发

AT指令控制、4G模块数据透传

5

数据存储

数据存储与读取

PIC单片机入门实战》共8篇文章与《PIC单片机进阶实战》共6篇文章与《PIC单片机高阶实战》5篇内容来源于我自己画的电路原理图及程序,有对PIC单片机感兴趣想学习的朋友可以关注我,免费赠送资料(包括原理图、数据手册、各种例程等)。

有需要这款开发板的朋友也可以关注联系我。

后续干货不断,咱们一起在单片机的世界里,共同进步。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐