【发布时间】:2017-09-16 11:36:37
【问题描述】:
我正在使用 PIC32MX250F128D 构建设备。其中一个系统需要使用 UART。从 PIC 传输到 putty 终端工作正常。但是,在另一个方向发送数据是行不通的,我没有想法。我正在使用使用 CP2102 芯片的廉价 USB-UART 适配器。 Link if relevant UART 使用引脚 25 和 26(RPC0/AN6 和 RPC1/AN7)。
- 如果启用了 TXEN 传输,则输入 putty 的任何字符都将返回并打印在 putty 上。即使交换了 RX 和 TX 线,也会发生这种情况。 PIC上的发送中断标志被触发
- 如果关闭了 TXEN 发送使能,则 putty 不会打印出任何字符。同样,换线时的行为相同。没有中断标志。
- 断开 RX 或 TX 线也会导致腻子没有回复。
- 使用调试器检查 URXDA RX 缓冲区数据标志,我发现无论设置如何,发送的内容都没有放入 RX 缓冲区。
- UART 环回未启用。这也在运行时使用调试器进行了检查。
- 将代码循环写入 TXREG 可以按预期工作,将字符打印到 putty。
- 常规代码从不与 TXREG 或 RXREG 交互。 TX 目前没有在我们的程序中使用,RXREG 仅在中断例程中处理,因为 RXIF 甚至 URXDA 曾经被标记,所以永远不会被调用。
简而言之,电线断开、TXEN 禁用和 TX IF 似乎表明这不是硬件或连接问题,而 PIC 实际上正在镜像它接收到的数据。但是,PIC 从来没有意识到它接收到了数据,没有镜像数据的代码,也没有启用环回。
我的 UART 相关设置代码如下。我正在使用许多外围设备,所以我还在底部包含了我的整个设置代码,以防问题出在外围设备冲突上。
//includes
#include <xc.h>
#include <strings.h>
#include <stdio.h>
#include <sys/attribs.h>//necessary for Interrupt declarations
//configuration
#pragma config IOL1WAY = OFF//allows multiple(?) Peripheal cnfigurations
#pragma config FNOSC = FRCPLL//use 8MHZ FRC with PLL as clock
#pragma config FPLLIDIV = DIV_2//PLL input = 4MHZ
#pragma config FPLLMUL = MUL_24//PLL output=96 MHZ
#pragma config FPLLODIV = DIV_2//48 MHZ Sysclock
#pragma config FPBDIV = DIV_2//24 MHZ peripheal Bus
#pragma config FWDTEN=OFF, CP=OFF, BWP=OFF, OSCIOFNC = ON
#pragma config JTAGEN = OFF // Disable JTAG
void setup_pps(void)
{
//asm volatile ("di");//disable all interrupts
SYSKEY = 0x0;
SYSKEY = 0xAA996655;
SYSKEY = 0x556699AA;
CFGCONbits.IOLOCK = 0;
U1RXRbits.U1RXR = 0b0110; // Set U1RX to RPC1
RPC0Rbits.RPC0R = 0b0001; // Set U1TX to RPC0
CFGCONbits.IOLOCK = 1;
SYSKEY = 0x0;
//asm volatile ("ei");//re-enable interrupts
}
void setup(void)
{
asm("di");//disable interrupts while performing setup
//Interrupt vector priorities
IPC8CLR = 0x0000001F; // clear priority/subpriority fields
IPC8SET = 0x0000000C; // set UART priority = 3, IPC8<4:2>
IPC8SET = 0x00000000; // set UART subpriority = 0, IPC8<1:0>
INTCONbits.MVEC = 1;//enable multivector interrupts
//***Pin Setup
setup_pps();
//**Digital GPIO Setup
//set all port pins to digital
ANSELA=0x0;
//Set all port pins to output
TRISA=0x0;
//SNIP
//## End Digital GPIO Setup
//** UART Setup
U1MODEbits.UEN=0b00;//Use only U1TX and U1RX pins
U1MODEbits.BRGH=1;//TODO:Determine Baud rate for Reach//note: non-highspeed takes multiple samples->probably better for noise
U1MODEbits.PDSEL=0;//TODO: Reach parity and data select
//U1MODEbits.RXINV=1;
U1STAbits.UTXISEL=0;//Transmit Interrupt type
U1STAbits.URXISEL=0b01;//01;//Receive Interrupt type-Interrupt when 1/2 full (4 bytes)
int fpb=24000000;
int baudrate =38400;//change to set baud rate
U1BRG=fpb/(4*baudrate)-1;//Baud rate Generator//use 16x if brgh=0
//IEC1SET=0x0200;//Transmit Interrupt enable/ should not be needed
IEC1SET=0x0100;//Enable receive interrupt
U1STAbits.URXEN=1;//Receive Enable
U1MODEbits.ON=1;//Enable UART
U1STAbits.UTXEN=1;//Transmit Enable Enable TODO:Determine if needed for reach
U1STAbits.URXEN=1;//Receive Enable
//## End UART Setup
//SNIP
asm("ei");//re-enable interrupts
return;
}
整个设置
//includes
#include <xc.h>
//#include <p32xxxx.h>
//#include <proc/p32mx250f128d.h>
#include "letters.h"//codes for 7 segment display
#include "pins.h"//refer to ports/latches by function
#include "other.h"//mainly state machine states
#include <strings.h>
#include <stdio.h>
#include "gps.h"//contains variables and functions of gps data
#include <sys/attribs.h>//necessary for Interrupt declarations
//#include <string.h>//may be used for string manipulation, such as selecting files
//#include <stdio.h>//will be needed for file open
//configuration
#pragma config IOL1WAY = OFF//allows multiple(?) Peripheal cnfigurations
#pragma config FUSBIDIO = OFF//USB ID controlled by port, not USB Module
#pragma config FVBUSONIO = OFF//USB VBUS controlled by port, not USB
#pragma config FNOSC = FRCPLL//use 8MHZ FRC with PLL as clock
#pragma config FPLLIDIV = DIV_2//PLL input = 4MHZ
#pragma config FPLLMUL = MUL_24//PLL output=96 MHZ
#pragma config FPLLODIV = DIV_2//48 MHZ Sysclock
#pragma config UPLLIDIV = DIV_2//4 MHZ USB PLL input
#pragma config UPLLEN = ON//Enable PLL for USB
#pragma config FPBDIV = DIV_2//24 MHZ peripheal Bus
#pragma config FWDTEN=OFF, CP=OFF, BWP=OFF, OSCIOFNC = ON
#pragma config JTAGEN = OFF // Disable JTAG
#pragma config FSOSCEN = OFF // Disable Secondary Oscillator
void setup_pps(void)
{
//asm volatile ("di");//disable all interrupts
SYSKEY = 0x0;
SYSKEY = 0xAA996655;
SYSKEY = 0x556699AA;
CFGCONbits.IOLOCK = 0;
U1RXRbits.U1RXR = 0b0110; // Set U1RX to RPC1
RPC0Rbits.RPC0R = 0b0001; // Set U1TX to RPC0
CFGCONbits.IOLOCK = 1;
SYSKEY = 0x0;
//asm volatile ("ei");//re-enable interrupts
}
void setup(void)
{
asm("di");//disable interrupts while performing setup
//Interrupt vector priorities
IPC2CLR = 0x001f; // clear priority/subpriority fields
IPC2SET = 0x0018; // set timer 2 int priority = 6, IPC2<4:2>
IPC2SET = 0x0000; // set timer 2 int subpriority = 0, IPC2<1:0>
IPC5CLR = 0x1f000000; // clear priority/subpriority fields
IPC5SET = 0x10000000; // set adc int priority = 4, IPC5<28:26>
IPC5SET = 0x00000000; // set adc int subpriority = 0, IPC2<25:24>
IPC7CLR = 0x001F0000; // clear priority/subpriority fields
IPC7SET = 0x00080000; // set USB priority = 2, IPC7<20:18>
IPC7SET = 0x00000000; // set USB subpriority = 0, IPC7<17:16>
IPC8CLR = 0x0000001F; // clear priority/subpriority fields
IPC8SET = 0x0000000C; // set UART priority = 3, IPC8<4:2>
IPC8SET = 0x00000000; // set UART subpriority = 0, IPC8<1:0>
IPC8CLR = 0x001F0000; // clear priority/subpriority fields
IPC8SET = 0x00140000; // set Input Change priority = 5, IPC8<20:18>
IPC8SET = 0x00000000; // set Input subpriority = 0, IPC8<17:16>
INTCONbits.MVEC = 1;//enable multivector interrupts
// INTEnableSystemMultiVectoredInt(); //Enable multi vector interrupts
// INTEnableInterrupts();//enable interrupts
//Clock Setup
OSCCONbits.UFRCEN=0; //USE PLL for USB //Hopefully default, otherwise unlock sequence required to write-->move to setuppps
//***Pin Setup
setup_pps();
//DEVCFG0bits.JTAGEN=0;
//DDPCONbits.JTAGEN = 0
//**Digital GPIO Setup
//set all port pins to digital
ANSELA=0x0;
ANSELB=0x0;
ANSELC=0X4;//leave C2/AN8 as analog
//Set all port pins to output
TRISA=0x0;
TRISB=0x0;
TRISC=0x4;
//Set Controller Ports to inputs
TRISBbits.TRISB5=1;
TRISBbits.TRISB7=1;
TRISBbits.TRISB8=1;
TRISBbits.TRISB9=1;
TRISCbits.TRISC6=1;
TRISCbits.TRISC7=1;
TRISCbits.TRISC8=1;
TRISCbits.TRISC9=1;
CNCONBbits.ON=1;//enable input change notification of port B
CNENBSET=0x0180;//enable input change notification on RB7 and RB8 (kill and mode switch)
tmp=PORTB;//clear mismatch
IFS1CLR=0x4000;//clear interrupt flag
IEC1SET=0x4000;//enable interrupt
//## End Digital GPIO Setup
//** UART Setup
U1MODEbits.UEN=0b00;//Use only U1TX and U1RX pins
U1MODEbits.BRGH=1;//TODO:Determine Baud rate for Reach//note: non-highspeed takes multiple samples->probably better for noise
U1MODEbits.PDSEL=0;//TODO: Reach parity and data select
//U1MODEbits.RXINV=1;
U1STAbits.UTXISEL=0;//Transmit Interrupt type
U1STAbits.URXISEL=0b01;//01;//Receive Interrupt type-Interrupt when 1/2 full (4 bytes)
int fpb=24000000;
int baudrate =38400;//change to set baud rate
U1BRG=fpb/(4*baudrate)-1;//Baud rate Generator//use 16x if brgh=0
//UxBRG = FPB / (4 * BAUDRATE) - 1//FPB = 24MHZ in current setup
//IEC1SET=0x0200;//Transmit Interrupt enable/ should not be needed
IEC1SET=0x0100;//Enable receive interrupt
U1STAbits.URXEN=1;//Receive Enable
U1MODEbits.ON=1;//Enable UART
U1STAbits.UTXEN=1;//Transmit Enable Enable TODO:Determine if needed for reach
U1STAbits.URXEN=1;//Receive Enable
//## End UART Setup
//** ADC Setup
//Behavior-Samples AN8 8 times automatically, then generates interrupt. Can read samples either in lower or upper half of buffer at a time.
ANSELCbits.ANSC2=0b1;//Set C2 as analog
TRISCbits.TRISC2=0b1;//Set C2 as input
AD1CON1bits.FORM=0b000;//16 bit integer result
AD1CON1bits.SSRC=0b111;//auto convert at end of sampling
AD1CON1bits.CLRASAM=0b1;//When interrupt happens, ASAM will automatically be cleared
AD1CON1bits.ASAM=0b1;//Auto start sampling at conversion end
AD1CON2bits.VCFG=0b000;//Use AVSS and AVDD as reference
AD1CON2bits.SMPI=0b1111;//Interrupt every 16th sample
AD1CON2bits.BUFM=0b0;//Buffer is not split
AD1CON3bits.ADCS=0b11;//TAD=4*TPB=167ns
AD1CON3bits.SAMC=0b01111;//Samples for 15 TAD=2.5uS
AD1CHSbits.CH0SA=0b1000;//Samples AN8
IEC0SET=0x10000000;//ADC1 INterrupt enable
AD1CON1bits.ADON=1;//Enable ADC
//## END ADC Setup
//**USB Setup
//TODO
//## END USB setup
//###END pin setup
//***Timer2 setup
//This will generate an interrupt every 10 ms to change the display.
T2CONbits.TCKPS=0b101;//1 Timer clock per 32 peripheral bus clocks
PR2=3750; //Interrupt flag every 10 ms at pbclk=24mhz
IEC0SET=0x0200;//Timer 2 Interrupt enable
T2CONbits.ON=0b1;//enable timer
asm("ei");//re-enable interrupts
return;
}
【问题讨论】:
-
1) 我们不是调试服务。 2) “简而言之,电线断开、TXEN 禁用和 TX IF 似乎表明它不是硬件或连接问题,并且 PIC 实际上是在镜像它接收到的数据。但是, PIC 从未意识到它收到了数据,没有代码来镜像数据,也没有启用环回。” - 自相矛盾。那是什么? 3) 使用调试器。
-
您是否检查过 USB 串行端口上的流量控制问题?如果没有来自 PIC32 的流量控制,它可能需要连接 RTS 和 CTS,并且需要连接 DTR、DSR 和 CD。这是 USB-Serial 设备的常见问题,在调试其他代码之前应检查。
-
@Olaf 我正在使用调试器,该描述是准确的。换句话说,PIC 将数据发送到计算机,但没有指明数据来自何处。根据发送的数据,它只能从逻辑上首先来自计算机,但在 PIC 的状态或其他寄存器中没有指示它收到了数据。
-
@Olaf 特别是一个pickit3
-
@janm 查看硬件流控制,我看到了一些选项。看起来我应该确保引脚处于正确的状态,如果它们不是,我也许可以将它们短路到正确的状态。一页提到这发生在更便宜的芯片上,所以我可能不得不买一根 FTDI 电缆。如果可能的话,我宁愿避免弄乱 RTS/CTS,因为引脚限制以及 UART 最终将用于与没有流量控制进行通信的设备。明天我会对此进行更多研究。
标签: c embedded pic uart microchip