dsPic Receive 11byte usart string - microchip

I'm using a dsPic33 to try and receive a 11-byte string and place it in a array, but have not been successful at receiving it completely. The string I send is "$123456789#" which should be received by the pic. I have tried using the code below. Any help will be appreciated.
char inBytes[11];
int i;
unsigned char temp;
while (U1STAbits.URXDA != 0)
{
temp = U1RXREG;
if (temp == '$')
{
inBytes[0] = temp;
for(i = 1; i < 10; i++)
{
if (U1STAbits.URXDA != 0)
inChar = U1RXREG;
inBytes[i] = inChar;
}
}

jolati had a good point about the end value beeing too low to get 11 bytes but I must add that you have to wait for your other bytes to become available before you read them.
In your example;
char inBytes[11];
int i;
unsigned char temp;
while (!U1STAbits.URXDA ); //Wait until at least one byte is available
temp = U1RXREG;
if (temp == '$')
{
inBytes[0] = temp;
for(i = 1; i < 11; i++) //Loop over range i = 1 to 10 inclusively
{
while (!U1STAbits.URXDA ); //Wait until at least one byte is available
inBytes[i] = U1RXREG;
}
}
Ideally, you would do this in a non blocking way with interrupts so you handle your data as it comes in but, if you cant use interrupts, you can always use non blocking polling like:
void AsyncRX()
{
//Note that the static variables keeps their value between invocations of the
// function. i is set to 0 only on the first run of this function, it keeps
// its value on every other run after that.
static int i = 0;
static char inBytes[11];
//Nothing more to do until there is at least 1 byte available
if( !U1STAbits.URXDA )
return;
//Save the byte and test that our message starts with $
inBytes[i] = U1RXREG;
if( inBytes[0] != '$' )
return;
//Test the counter to see if we have a full 11 bytes
i++;
if( i < 11 )
return;
//Do something with your 11 bytes
//...
//...
//Reset the counter for the next message
i = 0;
}
For the interrupt example, you could simply grab the polled version and throw it into a ISR. The following is an example. Note that I do not know which dsp33 you are using and I have not programmed interrupts in high end cores (with vector tables) in a while so you may need to make a change or two. Also note that you need to enable interupts by setting the appropriate registers as they are not enabled by default.
void __attribute__ ((interrupt, no_auto_psv)) _U1RXInterrupt(void)
{
//Note that the static variables keeps their value between invocations of the
// function. i is set to 0 only on the first run of this function, it keeps
// its value on every other run after that.
static int i = 0;
static char inBytes[11];
//Reset the interrupt flag
IFS0bits.U1RXIF = 0;
//Use up all bytes in the buffer (the interrupt can be set to only fire
// once the buffer has multiple bytes in it).
while( U1STAbits.URXDA )
{
//Save the byte and test that our message starts with $
inBytes[i] = U1RXREG;
if( inBytes[0] != '$' )
continue;
//Test the counter to see if we have a full 11 bytes
i++;
if( i < 11 )
continue;
//Do something with your 11 bytes
//...
//...
//Reset the counter for the next message
i = 0;
}
}

for(i = 1; i < 10; i++) starts saving data at index 1 and stops at 9, only 9 bytes. Change < 10 to <= 10 or < 11.

Related

Is it normal for winapi to take around 70ms to read from serial port?

The true time it takes from when I send the first bit to a serial port to when I receive the last bit it pings back I measured to be 6ms but ReadFile takes around 70-80ms. I'm wondering if this is expected, is this just Windows or is it my code at fault? Here's the function to send and read from the serial port, in my main I have declared and initialized the HANDLE and called that function.
int sendBytes(char* command, char* COM, HANDLE hSerial, int read) {
BOOL Write_Status;
DCB dcbSerialParams = { 0 }; // Initializing DCB structure
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
Write_Status = GetCommState(hSerial, &dcbSerialParams); //retreives the current settings
if (Write_Status == FALSE) {
printf("\n Error! in GetCommState()");
CloseHandle(hSerial);
return 1;
}
dcbSerialParams.BaudRate = CBR_57600;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
Write_Status = SetCommState(hSerial, &dcbSerialParams); //Configuring the port according to settings in DCB
if (Write_Status == FALSE)
{
CloseHandle(hSerial);
return 1;
}
///*----------------------------- Writing a Character to Serial Port----------------------------------------*/
int length = strlen(command);
char send[20];
strcpy(send, command);
send[length + 1] = 13;
send[length + 2] = 10;
DWORD dNoOFBytestoWrite; // No of bytes to write into the port
DWORD dNoOfBytesWritten = 0; // No of bytes written to the port
dNoOFBytestoWrite = length + 2; // Calculating the no of bytes to write into the port
if (!WriteFile(hSerial, send, dNoOFBytestoWrite, &dNoOfBytesWritten, NULL))
printf("Error writing text to %s\n", COM);
if (read) {
int maxChars = 100;
BOOL Read_Status; // Status of the various operations
DWORD dwEventMask; // Event mask to trigger
char SerialBuffer[100]; // Buffer Containing Rxed Data
DWORD NoBytesRead; // Bytes read by ReadFile()
///*------------------------------------ Setting Receive Mask ----------------------------------------------*/
Read_Status = SetCommMask(hSerial, EV_RXCHAR); //Configure Windows to Monitor the serial device for Character Reception
if (Read_Status == FALSE)
printf("\n\n Error! in Setting CommMask");
// else
// printf("\n\n Setting CommMask successfull");
///*------------------------------------ Setting WaitComm() Event ----------------------------------------*/
// printf("\n\n Waiting for Data Reception");
Read_Status = WaitCommEvent(hSerial, &dwEventMask, NULL); //Wait for the character to be received
// /*-------------------------- Program will Wait here till a Character is received ------------------------*/
if (Read_Status == FALSE)
{
printf("\n Error! in Setting WaitCommEvent()");
}
else //If WaitCommEvent()==True Read the RXed data using ReadFile();
{
// printf("\n\n Characters Received \t");
clock_t begin = clock();
if (!ReadFile(hSerial, SerialBuffer, 24, &NoBytesRead, NULL))
{
printf("wrong character");
return 1;
}
clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("time : %f\n",time_spent);
}
}
}
This is not how you measure timing with sub-second precision:
clock_t begin = clock();
// stuff
clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
This is how you measure timing:
LARGE_INTEGER before, after, frequency;
QueryPerformanceCounter(&before);
// stuff
QueryPerformanceCounter(&after);
QueryPerformanceFrequency(&frequency);
double time_spent = (after.QuadPart - before.QuadPart) / (double)frequency.QuadPart;
CLOCKS_PER_SEC is imprecise, and then clock() can be even worse, often as bad as the scheduler quantum which is typically 10ms or 15ms.

IR Receiver RC5 with Pic12F1572

I am building an IR Receiver with PIC12F1572 with receiver module TSOP2438
My objective of this project is to receive a data by remote control and send it to PC via UART..
I have done the code and I am testing it I can send the normal value through the UART but Somewhereis wrong so that I can not receive the hex values regarding the commands of remote control
Can anyone see my code and tell where I am goping wrong?
Here is my code
void main(void)
{
OSCILLATOR_Initialize(); // 0x78 for Fosc = 16Mhz
PIN_MANAGER_Initialize(); //All port pins Digital and input
EUSART_Initialize();
INTCONbits.IOCIF = 0; // Interrupt on-change Flag
INTCONbits.PEIE = 1; //SEt Peripheral Interrupt
INTCONbits.GIE = 1; //Set Global Interrupt
//while(!OSCSTATbits.HFIOFS); //Check here or wait here to OSC stable/ 0.5% accuracy
TRISAbits.TRISA2 = 1; //Configure R1 as input
// uint16_t Input_buffer [20];
EUSART_Write(0x40); // 0x40 = # some flag
while(1)
{
count = 0;
//while((IR_PIN)); //IR_PIN receives an IR signal its output pin goes from logic 1 to logic 0
//which causes the microcontroller to start reading the IR signal using the function. decode()
EUSART_Write(0x41);
//while(IR_PIN);
if(Decode()) //check if RC5 decoding- new data is arrived
{
EUSART_Write(0x42);
toggle_bit = bit_test(IR_Code, 11);
address = (IR_Code >> 6) & 0x1F;
command = IR_Code & 0x3F;
EUSART_Write(toggle_bit);
EUSART_Write(address);
EUSART_Write(command);
EUSART_Write(0x43);
}
}
}
/*----------*/
uint8_t Measure_space()
{
TMR0_Initialize();
while(IR_PIN && (count < 2000))
count = TMR0_ReadTimer(); //Read timer value and store it in count value
if((count > 1999) || (count < 700))
return 0; //0 = If width is out of range
if(count > 1200)
return 1; //1 = If width is long
else
return 2; //2 = If the width is short
}
uint8_t Decode()
{
uint8_t i = 0, check;
mid1:
check = Measure_Pulse();
if(check == 0)
return FALSE;
bit_set(IR_Code, 13 - i);
i++;
if(i > 13)
return TRUE;
if(check == 1)
goto mid0;
else
goto start1;
mid0:
check = Measure_space();
if((check == 0) && (i != 13))
return FALSE;
bit_clear(IR_Code, 13 - i);
i++;
if(i > 13) return TRUE;
if(check == 1)
goto mid1;
else
goto start0;
start1:
check = Measure_space();
if(check != 2)
return FALSE;
goto mid1;
start0:
check = Measure_Pulse();
if(check != 2)
return FALSE;
goto mid0;
}
I think this is because you are sending Hex value without converting to string. If you want to print this Hex value in PC terminal, First you have to convert it to ASCII string.

Error while freeing an array within a data structure

Status bit_flags_set_flag(BIT_FLAGS hBit_flags, int flag_position) {
Bit_Flags* temp = (Bit_Flags*)hBit_flags;
int* nums;
int i;
int old_size;
if (temp->size < flag_position) {
nums = malloc(sizeof(int)*flag_position+1);
if (nums == NULL) {
return FAILURE;
}
for (i = 0; i < temp->size; i++) {
nums[i] = temp->data[i];
}
free(temp->data);
temp->data = nums;
old_size = temp->size;
temp->size = flag_position + 1;
for (i = old_size; i < temp->size; i++) {
temp->data[i] = 0;
}
}
temp->data[flag_position / 32] |= 1 << flag_position % 32;
return SUCCESS;
}
according to the debugger the error is from the free(temp->data) part. however. I only run into the error the second time I go through the function. any ideas what is happening here.
am getting a heap corruption error on visual studio.
I am writing on some assumptions like you are assuming int size is 32 bits and you are trying to set the bit at flag_position in the bitset and you are using 1 int for 1 bit for setting and unsetting bits
Few comments now
temp->data[flag_position / 32] |= 1 << flag_position % 32; now this doesn't make any sense, this line role is to set bit at flag_position, this should be temp->data[flag_position] = 1; instead because if you see your code your are using ints for each bit.
Also this line temp->size = flag_position + 1; is also incorrect , this should be temp->size = flag_position;

bootloader avr atmega128RFA1

I am also working on the bootloader.
I had the problem in the following:
Once the cmd 'B' is received, later, 'F' is received, then I would start to call block load.
static void start_block_flash_load(uint16_t size, uint32_t *addr) {
uint16_t data_word;
uint8_t sreg = SREG;
uint16_t temp;
int i;
uint8_t my_size;
fprintf(lcdout, "B");
cli();
// Disable interrupts
(*addr) <<= 1;
if (size <= SPM_PAGESIZE) {
boot_page_erase(*addr);
boot_spm_busy_wait();
fprintf(lcdout, "%"PRIu16, size);
uint16_t i;
//store all values. PROBLEM here!!!
my_size = 208;
uint8_t buf[SPM_PAGESIZE] = { 0 };
for (i = 0; i < my_size; i++) {
//for (i=0; i<size; i++){
buf[i] = uart_getc();
// lcd_clear();
// lcd_setCursor(0, 2);
// fprintf(lcdout, "%3d", i);
// _delay_ms(500);
}
for (i = 0; i < my_size; i += 2) { //if size is odd, then use do-while
uint16_t w = buf[i];
w += buf[i + 1] << 8; //first one is low byte, second is high???
boot_page_fill((*addr)+i, w);
}
boot_page_write(*addr);
boot_spm_busy_wait();
(*addr) >>= 1;
uart_putc('\r');
} else
uart_putc('?');
boot_rww_enable ();
SREG = sreg;
}
I can see on the lcd that the size of the block is 256. However, when entering the loop to collect data, it will get stuck.
I tested with my_size and I found that only if my_size=208 the program will run further.
The strange thing is that if I put some statements inside the loop, e.g.
lcd_clear();
lcd_setCursor(0, 2);
then 'i' which I printed out on lcd will not go up to 140 something. I put different statements, the 'i' will give different value. That is very strange, since the uart_getc() will not lose data.
What I expect is that the loop will go up to 256. I cannot figure out what happened there.
Please help if you have any idea.
Thanks

Converting lower/upper case letters without ctype.h

I just saw that this could technically work, the only mistake I couldn´t resolve was the last ASCII character that gets printed everytime I test it out, I also tested this out without using the name variable, I mean just making a substraction of 32 to any lower case letter in ASCII should give me their upper case one and it does, but I´m curious on why I´m getting an additional char, wich from what I see in screen is apparently Û.
#include <stdio.h>
main()
{
char name[22];
int i;
fputs("Type your name ",stdout);
fgets(name,22,stdin);
for (i = 0; name[i] != '\0'; i = i + 1)
printf("%c",(name[i])-32); /*This will convert lower case to upper */
/* using as reference the ASCII table*/
fflush(stdin);
getchar();
}
Perhaps there is a line break character at the end of the string.
You can check the chararacter code, so that you only convert characters that actually are lower case letters:
for (i = 0; name[i] != '\0'; i = i + 1) {
char c = name[i];
if (c => 97 && c <= 122) {
c -= 32;
}
printf("%c", c);
}
void read_chararray(char in_array[], int* Length)
{
int Indx = 0, Indx2 = 0, Indx3 = 0; // int declarations for indexs of some loops
char cinput = { 0 }, word[255] = { 0 }, word2[255] = { 0 }; // declaration of cinput and first char array before punctiation removed
for (Indx = 0; (cinput = getchar()) != '\n'; Indx++) { // Loop for getting characters from user stop at <enter>
word[Indx] = cinput; // Placing char into array while changing to lowercase
}
Indx2 = Indx; // Set Indx2 to Indx for loop operation
for (Indx = 0; Indx < Indx2; Indx++) { // Loop to check and replace upper characters with lower
cinput = word[Indx];
if (cinput >= 65 && cinput <= 90) { // If cinput is within the ASCII range 65 and 90, this indicates upper characters
cinput += 32; // Add 32 to cinput to shift to the lower character range within the ASCII table
in_array[Indx] = cinput; // Input new value into array pointer
}
else if (cinput >= 97 && cinput <= 122) // scans if character are lower ASCII, places them in array irraticating punctuation and whitespce
in_array[Indx] = cinput; // Input remaining lower case into array pointer
}
*Length = Indx; // final size of array set to Length variable for future use
}
#include<stdio.h>
void upper(char);
void main()
{
char ch;
printf("\nEnter the character in lower case");
scanf("%c", &ch);
upper(ch);
}
void upper( char c)
{
printf("\nUpper Case: %c", c-32);
}

Resources