PIC32MX270F256B UART : how to get a single byte from the RX FIFO? - pic

I'm trying to read byte per byte from the RX FIFO, that's 8 bytes deep.
The problem is that when the first byte is received, I have to wait for 8 other bytes to finally get the first byte on U1RXREG.
I'd like to know how to perform some dummy reads on the FIFO to access a particuar byte and "flush" it. Simply putting U1RXREG in an array doesn't do the trick.
Here's my initialization :
void UART_Initialize(void)
{
// SIDL: Stop in Idle Mode bit : 1 = Discontinue module operation when the device enters Idle mode
U1MODEbits.SIDL = 0;
// IREN: IrDA Encoder and Decoder Enable bit : 0 = IrDA is disabled
U1MODEbits.IREN = 0;
// RTSMD: Mode Selection for UxRTS Pin bit : 0 = UxRTS pin is in Flow Control mode
U1MODEbits.RTSMD = 0;
// UEN<1:0>: UARTx Enable bits : 10 = UxTX, UxRX, UxCTS and UxRTS pins are enabled and used
U1MODEbits.UEN1 = 1;
U1MODEbits.UEN0 = 0;
// WAKE: Enable Wake-up on Start bit Detect During Sleep Mode bit : 0 = Wake-up disabled
U1MODEbits.WAKE = 0;
// LPBACK: UARTx Loopback Mode Select bit : 0 = Loopback mode is disabled
U1MODEbits.LPBACK = 0;
// ABAUD: Auto-Baud Enable bit : 0 = Baud rate measurement disabled or completed
U1MODEbits.ABAUD = 0;
// RXINV: Receive Polarity Inversion bit : 0 = UxRX Idle state is ‘1’
U1MODEbits.RXINV = 0;
// BRGH: High Baud Rate Enable bit : 0 = Standard Speed mode – 16x baud clock enabled
U1MODEbits.BRGH = 0;
// PDSEL<1:0>: Parity and Data Selection bits : 01 = 8-bit data, even parity
U1MODEbits.PDSEL1 = 0;
U1MODEbits.PDSEL0 = 1;
// STSEL: Stop Selection bit : 0 = 1 Stop bit
U1MODEbits.STSEL = 0;
// ADM_EN: Automatic Address Detect Mode Enable bit : 0 = Automatic Address Detect mode is disabled
U1STAbits.ADM_EN = 0;
// UTXISEL<1:0>: TX Interrupt Mode Selection bits : 00 = Interrupt is generated and asserted while the transmit buffer contains at least one empty space
U1STAbits.UTXISEL1 = 0;
U1STAbits.UTXISEL0 = 0;
// UTXINV: Transmit Polarity Inversion bit : 0 = UxTX Idle state is ‘1’ (with IrDA disbled)
U1STAbits.UTXINV = 0;
// URXEN: Receiver Enable bit : 1 = UARTx receiver is enabled. UxRX pin is controlled by UARTx (if ON = 1)
U1STAbits.URXEN = 1;
// UTXBRK: Transmit Break bit : 0 = Break transmission is disabled or completed
U1STAbits.UTXBRK = 0;
// URXISEL<1:0>: Receive Interrupt Mode Selection bit : 00 = Interrupt flag bit is asserted while receive buffer is not empty (i.e., has at least 1 data character)
U1STAbits.URXISEL1 = 0;
U1STAbits.URXISEL0 = 0;
// ADDEN: Address Character Detect bit (bit 8 of received data = 1) : 0 = Address Detect mode is disabled
U1STAbits.ADDEN = 0;
// Baud Rate Calculation :
// FPB = 10MHz ; Desired Baud Rate = 9600 bauds
// => U1BRG = FPB/(16*BaudRate)-1 = 64 (error = 0,16%)
U1BRG = 64;
// Enable UART RX interrupts
//IEC1bits.U1RXIE = 1;
// Enable UART
// ON: UARTx Enable bit : 1 = UARTx is enabled. UARTx pins are controlled by UARTx as defined by the UEN<1:0> and UTXEN control bits.
U1MODEbits.ON = 1;
// UTXEN: Transmit Enable bit : 1 = UARTx transmitter is enabled. UxTX pin is controlled by UARTx (if ON = 1).
U1STAbits.UTXEN = 1;
}
For the moment I tried reading like this, in the while(1) loop, without success :
while (1)
{
uint8_t rxbyte[8];
bool b;
//if (U1STAbits.URXDA == 1)
while(!U1STAbits.URXDA);
rxbyte[0] = U1RXREG;
rxbyte[1] = U1RXREG;
rxbyte[2] = U1RXREG;
rxbyte[3] = U1RXREG;
rxbyte[4] = U1RXREG;
rxbyte[5] = U1RXREG;
rxbyte[6] = U1RXREG;
rxbyte[7] = U1RXREG;
sprintf(s, "I received : %u %u %u %u %u %u %u %u\n\r", rxbyte[0], rxbyte[1], rxbyte[2], rxbyte[3], rxbyte[4], rxbyte[5], rxbyte[6], rxbyte[7]);
myPrint(s);
IFS1bits.U1RXIF = 0;
}
The 8 bytes in rxbytes[] are always the same. I tried to clear the RX interrupt flag between the reads, reading URXDA also between the reads, add a delay, still no success, I still have to wait for 8 incoming bytes to access the first one.
Thanx in advance for your help !
Best regards.
Eric

I finally found the solution : I had a double configuration, one by MCC and one by myself, and it seems that having the interruptions activated caused this. Now I switched the interrupts off and I simply poll URXDA, and everything works fine.
Sorry for bothering you guys !

You can use your original method too. The problem with your While(1) loop is that you check if there is "at least 1 byte in the hardware Rx buffer" ( U1STAbits.URXDA tells you as soon as 1 byte is availlable ). When 1 byte is availlable, then you read 8 bytes inside the loop... so of course you will get 8 identical bytes when there is only 1 byte in the buffer.

Related

Problem in Flash Programming of PIC24FJ128GC006

I am making a USB Bootloader for PIC24FJ. I am now in the process of writing to flash memory the application code hex file through a software and without using ICD3. After downloading the application code hex file, I checked the program memory of the PIC using the PIC Memory Views of MPLAB Window Toolbar, and this is what it looks like. PIC24_BOOT_APP_VECTOR_AREA As you can see in the picture, the opcode is not continuously written in every address. It alternates with 000000.
Also I compared the opcodes of the downloaded app code using the bootloader, to the application code without using the bootloader. I have found out that there are data in the opcodes that are not present in the application alone. Attached are the photos. Application_Code_Alone_User_Area, PIC24_Boot_App_User_Area This may create a problem in jumping to the application.
Below is my code for storing data in the buffer and writing to flash memory. (I use single word programming for flash)
#define WRITE_FLASH_BLOCK_SIZE 0x04
#define USER_MEM_START_ADDRESS 0x004002
unsigned long rxBuff[60];
int rxIndexer;
int xfer;
lineStart = rxBuff[ 0 ];
positionAddress = (rxBuff[ 2 ] << 8) + (rxBuff[ 3 ]); // THIS IS THE ADDRESS WHERE THE DATA SHOULD BE ADDRESSED
numberOfData = rxBuff[ 1 ]; // THIS IS THE TOTAL NUMBER OF DATA RECEIVED IN THE STREAM
recordType = rxBuff[ 4 ];
rxIndexer = 5; //Start of data index in a INTEL Hex file format
for(xfer = 0; xfer < numberOfData; xfer += WRITE_FLASH_BLOCK_SIZE) // THIS SECTION CONTAINS THE PROCESS OF COMBINING THE INFORMATION
{ // FROM THE DATA STREAM TO THIS FORMAT - 0x00AA, 0xBBCC
rxBuff[rxIndexer] = ((rxBuff[START_OF_DATA_INDEX + xfer]) &0x00FF);
rxBuff[rxIndexer] |= ((rxBuff[START_OF_DATA_INDEX + xfer + 1] << 8) &0xFF00); //end of lower word
rxIndexer++;
rxBuff[rxIndexer] = ((rxBuff[START_OF_DATA_INDEX + xfer + 2]) &0x00FF); //start of upper byte
rxBuff[rxIndexer] |= ((0x00 << 8) & 0xFF00); // phantom byte (0x00)
rxIndexer++;
}
if(lineStart == ':')
{
if(recordType == 0x00 && data_checksum == 0)
{
for(xfer = 0; xfer < numberOfData; xfer += 2)
{
FlashWrite_Word(programAddress + positionAddress, rxBuff[5 + xfer], rxBuff[5 + xfer + 1]);
positionAddress += 2;
}
}
else if(recordType == 0x04 && data_checksum == 0)
{
programAddress = USER_MEM_START_ADDRESS;
}
else if( recordType == END_OF_FILE_RECORD)
{
jumpTo_App();
}

How to define Rb0 to Rb6 = hex (x%10); // no Rb7 pin

Using MikroC Pro for PIC16f73 to multiplexing 7 segment the written program is:
PORTB = Hex (x%10);
There PORTB means RB0 to RB7 total 8 pins are includes, but I want to use only 7 pins for 7 segments RB0 to RB6, and the pin RB7 as other O/P just 0 or 1.
As like Rb0 to Rb6 = hex (x%10) and Rb7_bit = 0 or 1
so how to define the line Rb0 to Rb6 = hex (x%10);
Try this:
uint8_t Pin_Value;
Pin_Value = Hex (x%10);
Pin_Value |= 0x80; //set bit RB7
Pin_Value &= 0x7F; //clear bit RB7
PORTB = Pin_Value;

Mifare Classic 1K reading fail with PN532 chip

I have PN532 chip for NFC and my board is connected to it by SPI. I am shure, that connection is good (Mifare UL totally works). I have some blank 1K classic cards, and there is some troubles.
My moves:
1) Setup PN532 (retries, SAM)
2) search for card by ListPassiveTarget command for ISO14443A cards
3) when card is found, authenticate to some sector (required block_number = sector_number * 4)
4) read data by 4 InDataExchange commands. Required block_number = sector_number * 4 + 0, 1, 2, 3.
5) go to step 3
First sector read is ok, I have some good data. But when I try to read other sector after succesfull authorisation to it, I have an error like I failed authentication.
I tried to read sector 0 (OK), then sector 1..15 read is failed.
I tried to read sector 5 (OK) with all block_num calculations (20,21,22,23 block), then sector 6..15 read is failed.
I tried to remove card from field for a minute, return card to field and repeat reading - and I cant read any sector. Only rebooting helps.
I suppose, that there can be some move between authentications. Typical HALT command is not helping.
Authentication function is tested - wrong keys dont work, wright keys are working.
My code, that dealing with reading:
// here we know card type
// ISO 14443 A MIFARE CLASSIC 1K
// repeat polling
if( !ListPassiveTarget_14443A_106() )
{
// no card!
NFC_download = false;
break;
}
else
{
if( !GetGeneralStatus() )
{
// no card!
NFC_download = false;
break;
}
else
{
if( NFC::Num_Of_Tg != 0 )
{
// 14443 A Mifare Classic
// 16 sectors, 4 blocks in each
for(u8 sector = 0; sector < 16; sector++) // for all 16 sectors
{
// autentificate sector with A key
u8 x = 0;
for(x = 0; (x < 3) && (Autenticated == 0); x++) // loop for keys
{
Autenticated = Try_Mifare_Classic_Key( x, 0, sector ); // try A key
// block = sector*4
}
if( Autenticated != 0 )
{
// send up success and key num
// uart send
if( ((Uart::CommandTX_WPos + 1) & 0x0F) != Uart::CommandTX_RPos )
{
// ok
Uart::CommandTXBuf[Uart::CommandTX_WPos].Size = 4;
Uart::CommandTXBuf[Uart::CommandTX_WPos].Buf[0] = AUTH_CLASSIC;
Uart::CommandTXBuf[Uart::CommandTX_WPos].Buf[1] = Autenticated; // key type
Uart::CommandTXBuf[Uart::CommandTX_WPos].Buf[2] = x; // key number
Uart::CommandTXBuf[Uart::CommandTX_WPos].Buf[3] = sector; // sector
Uart::CommandTX_WPos = (Uart::CommandTX_WPos + 1) & 0x0F;
Uart::commandSend();
}
// read all the sector
Read_Mifare( sector*4 );
Read_Mifare( sector*4 + 1);
Read_Mifare( sector*4 + 2);
Read_Mifare( sector*4 + 3);
// reboot card?
//SPI::Wait(5500000); // 1000 ms delay
//Halt_Mifare(); // halt wont help
//SPI::Wait(550000); // 100 ms delay
}
}// for sectors
}
else
{
// no target
NFC_download = false;
break;
}
}
}
What can be wrong? I have missed some moves between sector authentications and readings?
Fail in logic. Forgot to clear authentication flag. Now it's working.

Real time serial data acquisition

I wish to take the samples from pic16f877a,4Mhz HS( if it is given a sine wave input) and plot the same.I am giving 230vp sine wave 50hz as input and transformed it into 5v range and level shifted it into positive voltages.
This is my code
// Loop variable
float val,val1;//Declare the adcvalue stored variables
char uart_rd[50],uart_rd1[50];
void rmsv();
void adc_uart();//adc read and uart write
void interrupt(){
if (PIR1.ADIF) {
PIR1.ADIF=0; // clear AD interrupt flag
val= (ADRESH << 8) | ADRESL; // read dadta from channel 0
{
val1=(val*325.0)/1023.0;
FloatToStr(val1,uart_rd1);
strncpy(uart_rd,uart_rd1,3);
UART1_Write_Text(uart_rd1);
//UART1_Write(10);
UART1_Write(13);
delay_us(1);
}
Delay_Cyc(3); //wait acquisition time
ADCON0.F2=1; //start conversion again
}
}
void main()
{
TRISA=0XFF;//porta as input
ADCON1 = 0x82; // AN0->AN4 selected as analog input
ADCON0 = 0b11000001; // Configue analog mode
INTCON.GIE = 1; //Enable global interrupt
INTCON.PEIE = 1; //Enable peripheral interrupt
PIE1.ADIE = 1; //Enable ADC interrupt
Delay_us(20); //wait for acquisition time
ADCON0.F2 = 1; //start conversion
// ADCON1=0X81;
UART1_Init(9600); // Initialize UART module at 9600 bps
//ADC_Init();
while(1);
}
I have checked the values in hyperterminal and see that the controller not even sample the peak voltage.I wish to have the samples correctly so that I can able to plot the waveform correctly
Probably it is not a software problem. You say "controller not even sample the peak voltage" and that the signal rage is between 5V and 0V. Well, if you have configured your PIC ADC using the PIC power voltage (Vp) as reference voltage and if the power voltage is less than 5V ( Vp<5V), then your max adc Voltage range is Vp. It could cause that the peak of the sin signal after ADC acquisition looks cut.
Vp ________ _________ _________
\ / \ /
\ / \ /
\ / \ /
\ / \ /
0 \_/ \_/
Measure the power voltage on the PIC pin and if it is the reason then adjust the voltage source or transform the signal into Vp range .

Writing into Each LBA on Disk

There is a need to write into each LBA on the disk using SCSI CDB. Here i have constructed a while/for loop for writing into each LBA. I am using 10 byte CDB .
How do i represent 32 bit LBA so that it iterates from LBA 0 to Maximun LBA . What should be the data Tranfer lenght if i am planning to write on each LBA . Each LBA size 512 bytes.
for(i=0;i<=max_lba;i++)
{
ccb->cam_flags = DATA_OUT;
ccb->cdb[0] = 0x2A; /* 0x2A SCSI Opcode for write 10 CDB */
ccb->cdb[1] = 0;
ccb->cdb[2] = ?? ( LBA )
ccb->cdb[3] = ?? ( LBA )
ccb->cdb[4] = ?? ( LBA )
ccb->cdb[5] = ?? ( LBA )
ccb->cdb[6] = 0;
ccb->cdb[7] = ?? /* Data Transfer Length */
ccb->cdb[8] = ?? /* Data Transfer Length */
ccb->cdb[9] = 0;
ccb->ccb_address = (long)ccb;
ptr_data = (byte *)(buffer + ccb->data_buf_ptr);
data_pattern = i + (i << 4);
buffer[ccb->data_buf_ptr ] = data_pattern;
}
Assign the lba similar to this (but note that it will be really slow if you are going to write all of a large drive ... so it would be better if you write a large number of blocks, perhaps 1MB then adjust the next LBA accordingly).
cdb[2] = (i & 0xFF000000) >> 24;
cdb[3] = (i & 0xFF0000) >> 16;
cdb[4] = (i & 0xFF00) >> 8;
cdb[5] = (i & 0xFF);
For the above, set the number of blocks to 1:
cdb[7] = 0;
cdb[8] = 1;
Again, you will be waiting all day for a large drive so make the changes to write a large number of blocks in each iteration of the loop.

Resources