Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Uart communication between two different microcontrollers

Status
Not open for further replies.
Post the AT90 code which puts usb data to uart transmit and the code of ATMega32A which receives the data from AT90USB and checks for the command and performs some action.

I am posting the code for both the micro controllers. I have the ATmega32A code which is working perfectly with UART to PC. I have the code for AT90USB1287 which also working good via USB to PC. I have implemented UART functionality for AT90USB1287 using same method to ATmega32A.

I have connected both the boards using MAX232 conversion. Help me please.
 

Attachments

  • code (1).zip
    16 KB · Views: 55

Hi,
I have implemented UART Tx and rX FOR AT90USB1287 and i am able to receive data which i am sending from ATmega32A to PC via usb. I am trying to send commands from PC to ATmega32A via usb controller, it is also working, i have checked it with by shorting RX and Tx of AT90usb1287 board. it is returning to pc what ever i send the command as well as ATmega32 also receiving this command and performing action but it is not displaying in the PC. somewhere the USB communication is hanging. I am using putty, once i send command to the atmega via USB then putty terminal is hanging (inactive).

I have tested like, i have sent one command from PC to Atmega32 via usb controller. After that putty is going to hang mode. so what i did means once i have sent the command then i have connected atmega32a directly to PC via UART. it is running automatically what ever command i have sent through usb when both are connected.

Please help me with this why it is hanging.If you are going to help me then i will send my latest code.
 

May be the ATMega32A is not sending data properly to AT90USB using USART or may be AT90USB is not sending data using USB properly. Post your new code.

yes, the code is too long i have attached entire files for both controllers.

- - - Updated - - -

In the above files, turbopvt is related to AT90usb and bvr is related to ATmega. In at90usb I have implemented UART tx in "getcom" function in interface.c because i have written like the command is for at90 then execute otherwise calling uart_puts(Compare).
 

Attachments

  • TurboPVT_2.2.zip
    1 MB · Views: 52
  • bvr.zip
    374.4 KB · Views: 45

veerubiji, you should explain what you had to do to fix the problem. Maybe others in the future stumble in to the same problem.
 

I have connected two boards GND along with USART Tx, Rx and ground.

I have one more problem with this communication between two microcontrollers using USART. I have the interface code for both controllers like this.

I have the first board with AT90USB1287 microcontroller which is connected to PC using USB, I have several commands like this "CMD", "TEMP" ... When i send command it gives the response. Which is working perfectly. I have to connect another board which contains ATmega32A microcontroller to this board using USART. I have connected and I implemented USART communication in both boards, even the second board also have the similar type of command format and i need to send command to get response as well.
To send the Command from PC to second board i have to send the command first to AT90USB1287 board using USB communication and from that to ATmega32A using USART. I have done that and i am able to get response from second board also but i have one problem. What happening with my code is whatever command i send from PC it is sending to second board, i need to change like only commands which exist in second board has to sent to the second board.

1) Code for first board (AT90USB1287).
Code:
#include <90usb1287.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <interface.h>
#include <uart_drv.h>
                                                           
#define CMD_SIZE     57
#define USB_CMD_SIZE     52
flash unsigned char * flash cmdList[CMD_SIZE] = {
    "",             // [0] no com
    "INF",          // [1] Displayes version date etc.
    "RESET",        // [2] Reset CPU
    "boot",         // [3] Goto boot
    "DUMP",         // [4] Display manual debug info
    "AUT",          // [5] Start automatic scanning
    "STOP",         // [6] Stop scanning
    "STAF",         // [7] Set start frequency
    "STOF",         // [8] Set stop frequency
    "RES",          // [9] Display manual debug info
    "RATE",         // [10] Display manual debug info
    "GAIN",         // [11] Set gain
    "SCAN",         // [12] Start custom scan
    "SETUP",        // [13] Display manual scan setup info
    "TEMP",         // [14] Set temperature (Celsius)
   .....................
   ...................... (52 commands for USB board and 5 commands for ATmega32A board )
    
};



/***************************************************
C O M U N I C A T I O N  RS-232
****************************************************/
unsigned char SerIn[SIBUFSIZE];     // Input buffer (raw data)
unsigned char RxCnt;                // Location of next byte to be written
unsigned char RdCnt;                // Location of next byte to be read
unsigned char BufCnt;               // Size of unread contents in ring buffer
unsigned char CompIndex;            // Index in Copmare array
unsigned char Compare[COMPBUFSIZE]; // Command string tokenizer

unsigned char Uart_CompIndex;            // Index in Copmare array

unsigned char Command;              // Current Command is executed
unsigned int  Param;                // Parameter used in command
       float  Param2;               // Optional (second) parameter used in command
unsigned long Param3;               // Optional (third) parameter in command

extern unsigned char Plot;
unsigned char Step;


// USART1 Receiver interrupt service routine
interrupt [USART1_RXC] void usart1_rx_isr(void){   

char status,data;
status=UCSR1A;
data=UDR1;

printf("%c", data);

}

// USB Receive
void catchString(void){
    
    while(UEBCLX){
    
        if(++BufCnt >= SIBUFSIZE){               // Increment & check for buffer overflow  
            BufCnt = SIBUFSIZE-1;                // Set to max value 
//            printf("!Overflow\r\n");
//            UENUM = 2;   
            return;                              // Skip char
        }else{                                   // Else: if buffer ok
            if(++RxCnt >= SIBUFSIZE) RxCnt = 0;  // Increment read counter, if 10 -> 0 (max 9)
            SerIn[RxCnt] = UEDATX;               // Write to SBUF (load the transmit register)
        }
     }  
}


// Read from ringbuffer
char getcharb(void){

    if(BufCnt){                                 // If anything
        BufCnt--;                               // Decrement buffer counter
        if(++RdCnt >= SIBUFSIZE) RdCnt = 0;     // Increment read counter, if 10 -> 0 (max 9)
        return SerIn[RdCnt];                    // Read from SBUF (access receive register)
    }
    return 0;
}

void help(void){

      unsigned char  i;
        
      printf("Commands: ");
      for(i=0;i<CMD_SIZE;i++){
            printf(cmdList[i]);
            printf(", ");
      }printf("\r\n");
}



/***************************************************
S T R I N G   T O K E N I Z E R
Searches the input buffer for valid commands
returns the id of the command if a match is found or 0 if no cmd   
****************************************************/
                                                                 
void getcom(void){
      
      unsigned char c;
int comp_i=0;
       
      // Read from ring-buffer and fill in Compare buffer
      while(BufCnt){                          // while unread contents in ring-buffer
            c = getcharb();                    // fetch next byte
//  uart_putchar(c);

            if(CompIndex >= COMPBUFSIZE) CompIndex = 0;// overflow protection                    
            // Analyze char
            if(c == '#'){                     // Manual start
                  CompIndex = 0;
uart_putchar(c);
            }else if(c == '\r'){              // CR continue (end of cmd without argument)                         
                  Compare[CompIndex]='\0';    // fill in end character of comp string
uart_putchar(c);
                  break;                      // possible valid cmd received -> check out
            }else if(c == '\n'){              // New line (ignore)                         
                  // Do nothing (ignore)
            }else if(c == 8){                 // Backspace
                  if(CompIndex) CompIndex--;  // decrement index
         uart_putchar(c);
            }else if(c == 9){                 // Horizontal TAB 
                  help();                     // Write out cmds
         uart_putchar(c);

            }else if(c == 27){                // ESC button
                  Command = 0;                // Stop current command
		uart_putchar(c);

                  Param = 0;                  // Clear argument
                  Plot = 0;                   // Stop plotting
                  Step = 0;
            }else{
                  Compare[CompIndex++]=c;     // Default action: Store character
        uart_putchar(c);
            }if(!BufCnt) return;              // if no more data to read -> exit                                          
      }CompIndex=0;                           // reset, ready for next command
      
      c = 1;
                            
     
      while(c<CMD_SIZE){          // For each command       
            if(strncmpf(Compare,cmdList[c],strlenf(cmdList[c])) == 0) break;
            c++; 
      }
       
      if(c<USB_CMD_SIZE){             // If match on normal commands
            Command = c;      
            if(isdigit(Compare[strlenf(cmdList[c])])){
                  Param = atoi(&Compare[strlenf(cmdList[c])]);
                  c = strpos(Compare,':');                 
                  if(c > 0){
                        Param2 = atof(&Compare[c+1]);
                        c = strrpos(Compare,':');
                        if(c > strpos(Compare,':')) Param3 = atol(&Compare[c+1]);
                        else  Param3 = 0; 
                  }else{ 
                    Param2 = 0;
                    Param3 = 0;
                  }
            }else{
                Param  = 0;
                Param2 = 0;
                Param3 = 0;
            }
            printf("@%s\r\n",&Compare); //Ack command
      }else{

      if(c>CMD_SIZE-1){             // If match on normal commands

         //   printf("&E;1;\r\n");  // Command not found
        //    printf("->Unknown command: '%s'\r\n",&Compare); // If no match
            Command = 0;
             Param  = 0;
             Param2 = 0;
             Param3 = 0;
	}
      }
          
}
the function " uart_putchar(c); " is sending the command from this board to second board.

2) interface code for ATmega32A.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <interface.h>
#include <MEGA32.h>
#include <stdint.h>
#include <main.h>
#include "delay.h"


flash unsigned char *cmdList[CMD_SIZE] = {
    "NO_COM",       // [0] no com
    "PINF",          // [1] Displays version date etc.
    "SCAN",         // [2] 
    "WGF",          // [3] 
    "WGP",          // [4] Read Flash memory log (stopLog)
    "ADC"          // [5] Clear Flash memmory (stopLog)   
   
};


/***************************************************
C O M U N I C A T I O N  RS-232
****************************************************/
unsigned char CompIndex;            // Index in Copmare array
unsigned char Compare[COMPBUFSIZE]; // Command string tokenizer
extern unsigned char Command;              // Current Command is executed
extern unsigned int  Param;                // Parameter used in command
//       float  Param2;               // Optional (second) parameter used in command
//unsigned long Param3;               // Optional (third) parameter in command

unsigned char Step;

extern unsigned char state;
extern unsigned int status;
extern unsigned char debug;

#define RXB8 1
#define TXB8 0
#define UPE 2
#define OVR 3
#define FE 4
#define UDRE 5
#define RXC 7

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<OVR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)

// USART Receiver buffer
#define RX_BUFFER_SIZE0 32
char rx_buffer0[RX_BUFFER_SIZE0];

#if RX_BUFFER_SIZE0<256
unsigned char rx_wr_index0,rx_rd_index0,rx_counter0;
#else
unsigned int rx_wr_index0,rx_rd_index0,rx_counter0;
#endif

// This flag is set on USART Receiver buffer overflow
bit rx_buffer_overflow0;

// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void){
    char status,data;
    status=UCSRA;
    data=UDR;
    if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
       {
       rx_buffer0[rx_wr_index0]=data;
       if (++rx_wr_index0 == RX_BUFFER_SIZE0) rx_wr_index0=0;
       if (++rx_counter0 == RX_BUFFER_SIZE0)
          {
          rx_counter0=0;
          rx_buffer_overflow0=1;
          };
       };
}

#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+                               
char getchar(void){
    char data;
    while (rx_counter0==0);
    data=rx_buffer0[rx_rd_index0];
    if (++rx_rd_index0 == RX_BUFFER_SIZE0) rx_rd_index0=0;
    #asm("cli")
    --rx_counter0;
    #asm("sei")
    return data;
}
#pragma used-
#endif

// USART Transmitter buffer
#define TX_BUFFER_SIZE0 32
char tx_buffer0[TX_BUFFER_SIZE0];

#if TX_BUFFER_SIZE0<256
unsigned char tx_wr_index0,tx_rd_index0,tx_counter0;
#else
unsigned int tx_wr_index0,tx_rd_index0,tx_counter0;
#endif

// USART Transmitter interrupt service routine
interrupt [USART_TXC] void usart_tx_isr(void){
    if (tx_counter0){
        --tx_counter0;
        UDR=tx_buffer0[tx_rd_index0];
        if (++tx_rd_index0 == TX_BUFFER_SIZE0) tx_rd_index0=0;
        //#asm("WDR"); // For long words and slow baud-rates
    }
}

#ifndef _DEBUG_TERMINAL_IO_
// Write a character to the USART Transmitter buffer
#define _ALTERNATE_PUTCHAR_
#pragma used+
void putchar(char c){
    while (tx_counter0 == TX_BUFFER_SIZE0);
    #asm("cli")
    if (tx_counter0 || ((UCSRA & DATA_REGISTER_EMPTY)==0)){
        tx_buffer0[tx_wr_index0]=c;
        if (++tx_wr_index0 == TX_BUFFER_SIZE0) tx_wr_index0=0;
        ++tx_counter0;
    }
    else
    UDR=c;
    #asm("sei")
}
#pragma used-
#endif

void help(void){

      unsigned char  i;
        
      printf("Commands: ");
      for(i=0;i<CMD_SIZE;i++){
            printf(cmdList[i]);
            printf(", ");
      }printf("\r\n");
}

/***************************************************
S T R I N G   T O K E N I Z E R
Searches the input buffer for valid commands
returns the id of the command if a match is found or 0 if no cmd   
****************************************************/
                                                                 
void getCom(void){
      
      unsigned char c;
       
      // Read from ring-buffer and fill in Compare buffer
      while(rx_counter0){                     // while unread contents in ring-buffer
            c = getchar();                    // fetch next byte
            if(CompIndex >= COMPBUFSIZE) CompIndex = 0;// overflow protection                    
            // Analyze char
            if(c == '#'){                     // Manual start
                  CompIndex = 0;
            }else if(c == '\r'){              // CR continue (end of cmd without argument)                         
                  Compare[CompIndex]='\0';    // fill in end character of comp string
                  break;                      // possible valid cmd received -> check out
            }else if(c == '\n'){              // New line (ignore)                         
                  // Do nothing (ignore)
            }else if(c == 8){                 // Backspace
                  if(CompIndex) CompIndex--;  // decrement index
            }else if(c == 9){                 // Horizontal TAB 
                 // help();                     // Write out cmds
            }else if(c == 27){                // ESC button
                  Command = 0;                // Stop current command
                  Param = 0;                  // Clear argument
                  Step = 0;
            }else{
                  Compare[CompIndex++]=c;     // Default action: Store character
            }if(!rx_counter0) return;         // if no more data to read -> exit                                          
      }CompIndex=0;                           // reset, ready for next command
                                                   
      c = 1;                            
     
      while(c<CMD_SIZE){          // For each command       
            if(strncmpf(Compare,cmdList[c],strlenf(cmdList[c])) == 0) break;
            c++; 
      }
       
      if(c<CMD_SIZE){             // If match on normal commands
            Command = c;      
            if(isdigit(Compare[strlenf(cmdList[c])])){
                  Param = atoi(&Compare[strlenf(cmdList[c])]);
                 
            }else{   
                Param  = 0;
            }
            printf("@%s\r\n",&Compare); //Ack command
         }else{
//            printf("Command not found\r\n");   Command not found
//            printf("->??: '%s'\r\n",&Compare);  If no match
            Command = 0;
      }
          
}

Can anyone suggest me that how to stop sending all commands and send only those 5 commands which related to second board? Please help me with this.
 

Mention the commands that can be given for AT90USb and ATMega32 uCs. If both have the same commands then you should change it so that both devices will not respond to it. I see cmd SCAN is used by both. Change it to SCAN1 and SCAN2. When cmd is sent to AT90USB from PC it should check if command is any of the command is for ATMega32 and if yes, then only it should send the cmd to ATMega32 using USART.
 

Mention the commands that can be given for AT90USb and ATMega32 uCs. If both have the same commands then you should change it so that both devices will not respond to it. I see cmd SCAN is used by both. Change it to SCAN1 and SCAN2. When cmd is sent to AT90USB from PC it should check if command is any of the command is for ATMega32 and if yes, then only it should send the cmd to ATMega32 using USART.

Sorry its type mistake i think i have changed those SCAN to PSCAN. I understand the concept and even i am thinking same but i am not able to get some idea in implementing how to check the incoming command is for atmega32a? can help me with this please?

- - - Updated - - -

I have tried something like this.
I have created an array of commands for both controllers in single array like

Code:
#define CMD_SIZE    57
flash unsigned char * flash cmdListAT90[CMD_SIZE] = { 
    "",             // [0] no com 
    "INF",          // [1] Displayes version date etc. 
    "RESET",        // [2] Reset CPU 
    "boot",         // [3] Goto boot 
    "DUMP",         // [4] Display manual debug info 
    "AUT",          // [5] Start automatic scanning 
    "STOP",         // [6] Stop scanning 
    "STAF",         // [7] Set start frequency 
    "STOF",         // [8] Set stop frequency 
    "RES",          // [9] Display manual debug info 
    "RATE",         // [10] Display manual debug info 
    "GAIN",         // [11] Set gain 
    "SCAN",         // [12] Start custom scan 
    "SETUP",        // [13] Display manual scan setup info 
    "TEMP",         // [14] Set temperature (Celsius) 
   ..................... 
   ...................... (52 commands for USB board)
    "NO_COM",       // [0] no com 
    "PINF",          // [1] Displays version date etc. 
    "PSCAN",         // [2] 
    "WGF",          // [3] 
    "WGP",          // [4] Read Flash memory log (stopLog) 
    "ADC"          // [5] Clear Flash memmory (stopLog)    
    
};
in one array.....
I have created another array with same length like
Code:
flash unsigned char *dest(CMD_SIZE] = { 
    "L", //for nocom :remains local 
"L", // for INT :**seems** local 
"L","L","L","L","L","L","L","L","L","L",.......upto52 and after that is "A" for atmega.

"A" ......// for PSCAN: is atmega32 specific (5)
};

then i am thinking to compare the c or command index with the second array index. if it is "A" then send it to ATmega32A.? But i am not able to implement it? if possible can you help me how to do it?
 

When cmd is received through uart compare it with all commands and if it matches with any command for atmega32 then send it to atmega32.

Can you give some example code pls.... How to compare the received command with all commands? or In my method i am trying to compare index incoming command with index of destination array list or in any otherway? I am struggling with this from one week and i tried different ways nothing is worked.
 
Last edited:

strcmp(). See what value strcmp() returns if strings match or not. Depending on that value you decide whether to send the cmd to ATMega32 or not.
Hi,
I tried like this but i am not succeeded.

I have created one array with both controllers commands. I have declared two different command size's like 52 for usb and 57 for ATMega32.
Code:
#define CMD_SIZE    57 
#define USB_CMD_SIZE    52 
flash unsigned char * flash cmdList[CMD_SIZE] = { 
    "",             // [0] no com 
    "INF",          // [1] Displayes version date etc. 
    "RESET",        // [2] Reset CPU 
    "boot",         // [3] Goto boot 
    "DUMP",         // [4] Display manual debug info 
    "AUT",          // [5] Start automatic scanning 
    "STOP",         // [6] Stop scanning 
    "STAF",         // [7] Set start frequency 
    "STOF",         // [8] Set stop frequency 
    "RES",          // [9] Display manual debug info 
    "RATE",         // [10] Display manual debug info 
    "GAIN",         // [11] Set gain 
    "SCAN",         // [12] Start custom scan 
    "SETUP",        // [13] Display manual scan setup info 
    "TEMP",         // [14] Set temperature (Celsius) 
   ..................... 
   ......................  
    "NO_COM",       // [52] no com 
    "PINF",         // [53] Displays version date etc. 
    "PSCAN",         // [54] 
    "WGF",          // [55] 
    "ADC"          // [56] Clear Flash memmory (stopLog)       
};
My logic is if command index >52 like (c>USB_CMD_SIZE) then send to AT32 otherwise send to USB901287.
I have the code like this.
Code:
void getcom(void){
      
      unsigned char c;
int comp_i=0;
       
// Read from ring-buffer and fill in Compare buffer
      while(BufCnt){                          
            c = getcharb();                    
        if(CompIndex >= COMPBUFSIZE) CompIndex = 0;
            // Analyze char
            if(c == '#'){                     
                  CompIndex = 0;
            }else if(c == '\r'){                            
                  Compare[CompIndex]='\0';    
                  break;                      
            }else if(c == '\n'){              
                  // Do nothing (ignore)
            }else if(c == 8){                 
                  if(CompIndex) CompIndex--;  

            }else if(c == 9){      // Horizontal TAB 
                  help();          // Write out cmds

            }else if(c == 27){        // ESC button
                  Command = 0;// Stop current command

                  Param = 0;       // Clear argument
                  Plot = 0;     // Stop plotting
                  Step = 0;
            }else{
                  Compare[CompIndex++]=c;     
            }if(!BufCnt) return;                                     
      }CompIndex=0;                           
      
      c = 1;
      while(c<CMD_SIZE){          // For each command       
            if(strncmpf(Compare,cmdList[c],strlenf(cmdList[c])) == 0) break;
            c++; 
      }   
      
      if(c> USB_CMD_SIZE){ // this is for ATmega32
          Command = c;
           if(isdigit(Compare[strlenf(cmdList[c])])){
                  Param = atoi(&Compare[strlenf(cmdList[c])]);
                  c = strpos(Compare,':');                 
                  if(c > 0){
                        Param2 = atof(&Compare[c+1]);
                        c = strrpos(Compare,':');
                        if(c > strpos(Compare,':')) Param3 = atol(&Compare[c+1]);
                        else  Param3 = 0; 
                  }else{ 
                    Param2 = 0;
                    Param3 = 0;
                  }
            }else{
                Param  = 0;
                Param2 = 0;
                Param3 = 0;
            }              
               uart_putchar(Compare);
        //printf("@%s\r\n",&Compare); //Ack command
          }
       
      if(c<USB_CMD_SIZE){ //If match on normal cmnd
            Command = c;      
            if(isdigit(Compare[strlenf(cmdList[c])])){
                  Param = atoi(&Compare[strlenf(cmdList[c])]);
                  c = strpos(Compare,':');                 
                  if(c > 0){
                        Param2 = atof(&Compare[c+1]);
                        c = strrpos(Compare,':');
                        if(c > strpos(Compare,':')) Param3 = atol(&Compare[c+1]);
                        else  Param3 = 0; 
                  }else{ 
                    Param2 = 0;
                    Param3 = 0;
                  }
            }else{
                Param  = 0;
                Param2 = 0;
                Param3 = 0;
            }
            printf("@%s\r\n",&Compare); //Ack command
      }else{

      if(c>CMD_SIZE-1){             // If match on normal commands

         //   printf("&E;1;\r\n");  // Command not found
        //    printf("->Unknown command: 's'\r\n",&Compare); // If no match
            Command = 0;
             Param  = 0;
             Param2 = 0;
             Param3 = 0;
	}
      }       
}

I am not able to send the command using this function
Code:
uart_putchar(Compare);

I know that it takes one character but how to send the hole command.

even i tried like this

Code:
uart_putchar(C);
but nothing happend.

I have the uart_putchar function like this
Code:
void uart_putchar (char ch)
{
  while(!Uart_tx_ready());
  Uart_set_tx_busy(); // Set Busy flag before sending (always)
  Uart_send_byte(ch);
    
  return;
}

even i tried to change this like
Code:
void uart_puts(const char *s)
{
    while(*s)
    {
        uart_putchar(*s++);
	//	printf("*");
	}
}
but nothing is working for me. Can you help me?
 
Last edited:

Don't use a string array. Use seperate array for each string (Command). Compare each command of ATMega32 with the command that comes through usart.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
//ATMEGA32 Commands
 
unsigned char usartIN[];
unsigned char cmd0[] = "SCAN";
unsigned char cmd1[] = "NO_COM";
//...
 
if strcmp(cmd0, usartIN) || strcmp(cmd1, usartIN) || strcmp(cmd2, usartIN)...)
 
// send cmd to ATMEGA32.

 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top