Jump to content

Danny Higgins

EstablishedMember
  • Content Count

    42
  • Joined

  • Last visited

Community Reputation

0 Neutral

About Danny Higgins

  • Rank
    Regular
  1. this chip requires a 1Tcy between the port read and interrupt clear. Try an nop(); in there. As the key is human operated you could try polling every couple of ms. Cheers Reynard Many thanks Reynard. I tried removing the last return, but no change. I tried putting a NOP after reading portb but no change. Finally I tried your suggestion of reading portb only once into B_Current and it seems to be working. I doubt if I would have thought of that as a solution to the problem. Polling the morse key and PTT lines would have been a last resort as some morse dots are only 35 ms long and I have to mute the receiver, switch the antenna relay and start the transmitter without truncating the first character too much. Thanks again for your help, Danny
  2. Thanks Reynard. The key is an electronic one with logic gates driving an open collector transistor with 1nF across the contacts, so there should be no bounce. I've also tried setting a flag as soon as an interrupt occurs and I checked this flag to make sure that interrupts are not re-occurring before the first one finishes. The code in the interrupt routine has been kept short to prevent this also. I will try your other suggestion on Sunday when I get back home and I'll let you know the result. Danny
  3. I am building a PIC controller to control a transmitter. I have connected a morse key to RB4 with a 15kOhm pull up and I am trying to detect changes using interrupts on PORTB. The PIC is an 18F4525 running at 16.384 MHz. The PIC always seems to detect the morse key going down and switches on an LED, but about 5% of the time (apparently randomly) the LED is not switched off when the morse key is released. It starts to work again the next time the key is pressed. I have tried to detect switch bounce, but there does not seem to be any interrups occurring during the interrupt routine. I have tried disabling the MPLAB ICD2 and running with the program in the PIC but the results are the same. The attached code is about the minimum that shows the problem. The PIC sits in an endless loop waiting for an interrupt. In the interrupt routine a flag is set to say whether the morse key has gone up or down. If the flag is set, the main loop clocks the lamp status bits into a shift register to light the LEDs. The lamp flashing routine works if I just set it toggling the LEDs in a timing loop, so the problem seems to be detecting the rising edge on RB4. Any help or suggestions would be most welcome. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // My_Functions.c // // // // Controller_1.c // // // // Danny Higgins, G3XVR // // // // Version 1.1 20/09/2008 // // // // Input: Void // // // // Process: Set up parameters // // Initialise PIC // // If less than 5 characters in the transmit queue, get next message to be sent // // If there are received characters in the UART buffer, process them // // Scan keyboard // // Clock data out if Shift_Data_Flag is set // // // // Output: Continuous loop // // // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include <system.h> #include <icd2.h> #define LCD_ARGS 2, /* Interface type: mode 0 = 8bit, 1 = 4bit(low nibble), 2 = 4bit(upper nibble) */ \ 1, /* Use busy signal: 1 = use busy, 0 = use time delays */ \ PORTD, TRISD, /* Data port and data port tris register */ \ PORTA, TRISA, /* Control port and control port tris register */ \ 3, /* Bit number of control port is connected to RS */ \ 2, /* Bit number of control port is connected to RW */ \ 1 /* Bit number of control port is connected to Enable */ #include <lcd_driver.h> // include the LCD template code #include <stdio.h> #include <string.h> #include <ctype.h> #include <rs232_driver3.h> #include <i2c_driver_HW.h> #include "My_Defines.c" #include "My_PRAGMAs.c" #include "My_variables.c" #include "My_Subroutines.c" #include "My_Functions.c" void main (void) { initialise_PIC(); // Set I/O ports set_bit(intcon, GIE); // enable global interrupts set_bit(intcon, PEIE); // enable peripheral interrupts clear_bit(intcon, RBIF); // Clear any RB interrupt flags before enabling interrupt set_bit(intcon, RBIE); // Enable interrupts on PORTB changes while(1) { if(Shift_Data_Flag == 1) // Check to see if the flag is set for a lamp to change { Shift_Out(); // Send serial data out if flag is set Shift_Data_Flag = 0; // Reset flag } } } void interrupt(void) { if(intcon.0 == 1) // Check to see if PORTB has changed { if(((B_Status ^ portb) & 0x10) == 0x10) // Check for Key I/P change on RB4 { if(portb & 0x10) // Check for Key I/P Up { Lamp_TX_Active = 0; // Switch lamp OFF if key is up Shift_Data_Flag = 1; // Set flag to latch data out } else // If key is not up it must be down { Lamp_TX_Active =1; // Switch lamp ON Shift_Data_Flag = 1; // Set flag to latch data out } } B_Status = portb; // Remember new PORTB status intcon.0 = 0; // Clear RBIF for next interrupt } return; }
  4. Many thanks Ian. You have explained it extremely well. You can stop cringing now - I'm about to change all my "portx.y = 1" lines of code. Danny
  5. Thanks mchristisen and Reynard. I am writing to some port bits and reading from others, not mixing read and write on the same pin. Writing to one pin was OK, but when I wrote to another pin it reset the first pin, so I'm not quite sure what is happening. I will investigare further. Danny, G3XVR
  6. What is the recommended way of setting/clearing a single output line? Is there any difference between: PORTC.1 = 1; LATC.1 = 1; set_bit(PORTC, 1); set_bit(LATC, 1); Should individual output bits be declared as volatile? What is meant by a Read - Modify - Write operation in the PIC datasheets? Thanks, Danny, G3XVR
  7. I think I've found the problem. Interrupts were not happening (no void interrupt(void) routine)! Thanks, Danny
  8. Hi trossin. Thanks for the reply. The transmit buffer is 40 characters long and I don't send new messages until there is less than 5 characters in the txBuffer waiting to be sent. The maximum message length is only about 20 characters long, so the txBuffer does not overflow. I am testing it at the moment by sending a short string to an empty buffer and putting a breakpoint in MPLAB after the message has been sent. All of the message goes into the txBuffer but it is not all sent, depending on the delay I put in. 1ms delay is about the length of time it takes to send each character at 9600 baud, so I think this figure may be significant. This is the maximum data rate that the device can manage and it expects 7 bit data with EVEN parity. This is not an option with the hardware UART in the 18F4525 so I have to calculate the parity myself. Parity on receive is ignored. One other point I have noticed this afternoon. When a complete message has been sent the txout pointer is 1 in front of the txin pointer, so the second message may be truncated by 1 character at the start. I think that the issue is something to do with enabling/disabling the interrupts, but I can't find it. I'll have another go at posting the updated code: // My_UART.c // Hardware UART routines // // Danny Higgins, G3XVR // 24/03/2008 // // The UART is set for 7 bit operation with EVEN parity running at 9600 baud with a 16.384MHz clock frequency // Two circular buffers (rxBuffer and txBuffer) are used to receive and transmit characters. The buffer sizes // are determined by RX_BUFFER_SIZE and TX_BUFFER_SIZE which are currently set to 40 bytes each. EVEN parity // is set on transmitted characters and parity is ignored on received characters. txByteCount and rxByteCount // keep a track of the number of characters in each buffer waiting to be sent or read. If the buffers overflow // the oldest characters in the buffers get overwritten. There is no flow control or handshaking between the // the control unit and the receiver. // // The routines that send data to the receivers will only put data in the TX buffer when there are less than 5 // characters waiting to be sent. The longest command sent to the receivers is less than 20 characters. // // Known issues: // // This routine only works when there is a delay at the beginning of the putChar routine that puts characters // from commands into the txBuffer. With zero delay, only a NULL gets sent. With 250uS delay only a few characters // are transmitted. With a 1mS delay, all the characters seem to get sent. 1ms is about the time it takes to send // each character. // // When the delay is short enough to cause characters not to be sent, the characters are actually in the txBuffer // and the number of bytes waiting to be sent shows that there are characters waiting to be sent. When the delay // is long enough to send all the characters, the txout pointer to the next character to be transmitted is 1 ahead // of the txin pointer which puts the next message into the txBuffer. void serialInit() // Initialise the UART variables and registers { txByteCount = 0; // Number of bytes waiting to be sent in Buffer txIn = 0; // Point to beginning of TX_In Buffer txOut = 0; // Point to beginning of TX_Out Buffer rxByteCount = 0; // Number of bytes waiting in RX Buffer rxIn = 0; // Point to beginning of RX_In Buffer rxOut = 0; // Point to beginning of RX_Out Buffer txsta = 0x24; // dc, 8 bit, TX enabled, Async, 0, HighSpeed, trmt, tx9d spbrg = BAUD; rcsta = 0x90; // serial port enable, receive enable set_bit(pie1, TXIE); // Enable TX interrupt set_bit(pie1, RCIE); // Enable RX interrupt } void interruptRx() // Interrupt when a character is received in the UART { if (pir1&0x20 && pie1&0x20) { if (rcsta&0x02) // Clear overrun error { rcsta &= 0xEF; rcsta |= 0x10; } else if (rcsta&0x04) // Clear framing error { rxBuffer[rxIn] = rcreg; } else { rxBuffer[rxIn++] = rcreg & 0x7F; // Get byte from UART, ignore parity bit and put in RX Buffer if (rxIn >= RX_BUFFER_SIZE) // Check to see if reached end of RX Buffer { rxIn = 0; // If YES, point to start of RX Buffer } if (rxByteCount < RX_BUFFER_SIZE) // If RX Buffer not full ... { rxByteCount++; // ... increment number of bytes } else // keep only the last {RX_BUFFER_SIZE} bytes { rxOut++; // Increment the RX_Out Buffer pointer (loses a byte that has not been read) if (rxOut >= RX_BUFFER_SIZE) // Check to see if reached end of RX Buffer { rxOut = 0; // If YES, point to start of RX Buffer } } } } } void interruptTx() // Interrupt when txreg in UART is empty { if (pie1&0x10 && pir1&0x10) { // clear_bit(pie1,TXIE); // Disable interrupt txreg = txBuffer[txOut++]; // Send byte from TX Buffer to UART and increment TX_Out Buffer pointer if (txOut >= TX_BUFFER_SIZE) // Check to see if reached end of TX Buffer { txOut = 0; // If YES, then point to start of TX Buffer } if (txByteCount > 1) // If there were bytes waiting to be sent ... { txByteCount--; // ... decrement the number of bytes in the queue } else { txByteCount = 0; // If this was the last byte in the TX queue, set the queue length to zero clear_bit(pie1,TXIE); // Disable interrupt } } } char getRxByteCount() // Returns the number of bytes in RX Buffer waiting to be read { return rxByteCount; } char getChar(void) // Reads the next character from the RX Buffer { char temp = 0; if (rxByteCount > 0) // Return if nothing in the RX Buffer { temp = rxBuffer[rxOut]; // Save the character in the UART register clear_bit(pie1, RCIE); // Disable Rx interrupt rxOut++; // Point to next character in RX Buffer if (rxOut >= RX_BUFFER_SIZE) // If pointer is at the end of the buffer ... { rxOut = 0; // Put pointer back to start of buffer } rxByteCount--; // Decrement the number of bytes waiting to be read set_bit(pie1, RCIE); // Enable Rx interrupt } return temp; // Return the next character in the RX buffer } char getTxByteCount() // Returns the number of bytes in TX Buffer waiting to be sent { return txByteCount; } void putChar(char character) // Sets 7 bit EVEN Parity, puts a character in the TX Buffer and adjusts the pointers { delay_ms(1); // WHY ??? clear_bit(pie1,TXIE); // Disable Tx interrupt txBuffer[txIn] = Set_Parity(character); // set 7 bit EVEN parity and put in TX_In Buffer queue txIn++; // Increment pointer to TX_In Buffer if (txIn >= TX_BUFFER_SIZE) // Check to see if end of TX_In Buffer has been reached { txIn = 0; // If end of TX_In Buffer, then point to start of TX_In Buffer again } if (txByteCount < TX_BUFFER_SIZE) // If the TX_In Buffer isn't full ... { txByteCount++; // ... add 1 to the number of bytes in the queue } else // keep only the last {TX_BUFFER_SIZE} bytes { txOut++; // Increment the TX_Out Buffer pointer (overwrites a byte that has not been sent) if (txOut >= TX_BUFFER_SIZE) // If the pointer is at the end of the buffer ... { txOut = 0; // ... set it back to the beginning } } set_bit(pie1,TXIE); // Enable Tx interrupt } void sendString(const char * string) { char i = 0; // Point to first character in String while(string[i] != 0x00) // Put all of String (except final 0x00) ... { putChar(string[i++]); // ... into TX_Out Buffer } } char Set_Parity(char character) // sets 7 bit EVEN parity // Parity bit (character.7) = 1 if there are an ODD number of 1s in the byte { character.7 = 0; // reset parity (8th) bit if (character.0) character ^= 0x80; // toggle parity bit if (character.1) character ^= 0x80; // toggle parity bit if (character.2) character ^= 0x80; // toggle parity bit if (character.3) character ^= 0x80; // toggle parity bit if (character.4) character ^= 0x80; // toggle parity bit if (character.5) character ^= 0x80; // toggle parity bit if (character.6) character ^= 0x80; // toggle parity bit return character; }
  9. I have a problem sending ASCII characters via my hardware UART routine. I am using an 18F4525 at 16.384MHz sending 7 bit ASCII with EVEN parity at 9600 Baud. I need to put a delay in the putChar routine to get it to work. With no delay only a NULL is sent. With 250uS delay only the first few characters are sent and with a 1mS delay all the characters are sent. Can someone tell me why I need the delay? The sendString routine puts all of the characters into txBuffer but they are not all sent. If I stop after sending a truncated string, the txIn pointer is correct, but the txOut pointer and the txBtyeCount show that there are still characters in the buffer waiting to be sent. Apologies for code indents - I can't seem to find how to post code. Code: // My_UART.c // Hardware UART routines // // Danny Higgins, G3XVR // 22/03/2008 void serialInit() // Initialise the UART variables and registers { txByteCount = 0; // Number of bytes waiting to be sent in Buffer txIn = 0; // Point to beginning of TX_In Buffer txOut = 0; // Point to beginning of TX_Out Buffer rxByteCount = 0; // Number of bytes waiting in RX Buffer rxIn = 0; // Point to beginning of RX_In Buffer rxOut = 0; // Point to beginning of RX_Out Buffer txsta = 0x24; // dc, 8 bit, TX enabled, Async, 0, HighSpeed, trmt, tx9d spbrg = BAUD; rcsta = 0x90; // serial port enable, receive enable set_bit(pie1, TXIE); // Enable TX interrupt set_bit(pie1, RCIE); // Enable RX interrupt } void interruptRx() // Interrupt when a character is received in the UART { if (pir1&0x20 && pie1&0x20) { if (rcsta&0x02) // Clear overrun error { rcsta &= 0xEF; rcsta |= 0x10; } else if (rcsta&0x04) // Clear framing error { rxBuffer[rxIn] = rcreg; } else { rxBuffer[rxIn++] = rcreg & 0x7F; // Get byte from UART, ignore parity bit and put in RX Buffer if (rxIn >= RX_BUFFER_SIZE) // Check to see if reached end of RX Buffer { rxIn = 0; // If YES, point to start of RX Buffer } if (rxByteCount < RX_BUFFER_SIZE) // If RX Buffer not full ... { rxByteCount++; // ... increment number of bytes } else // keep only the last {RX_BUFFER_SIZE} bytes { rxOut++; // Increment the RX_Out Buffer pointer (loses a byte that has not been read) if (rxOut >= RX_BUFFER_SIZE) // Check to see if reached end of RX Buffer { rxOut = 0; // If YES, point to start of RX Buffer } } } } } void interruptTx() // Interrupt when txreg in UART is empty { if (pie1&0x10 && pir1&0x10) { clear_bit(pie1,TXIE); // Disable interrupt txreg = txBuffer[txOut++]; // Send byte from TX Buffer to UART and increment TX_Out Buffer pointer if (txOut >= TX_BUFFER_SIZE) // Check to see if reached end of TX Buffer { txOut = 0; // If YES, then point to start of TX Buffer } if (txByteCount > 1) // If there were bytes waiting to be sent ... { txByteCount--; // ... decrement the number of bytes in the queue } else { txByteCount = 0; // If this was the last byte in the TX queue, set the queue length to zero clear_bit(pie1,TXIE); // Disable interrupt } } } char getRxByteCount() // Returns the number of bytes in RX Buffer waiting to be read { return rxByteCount; } char getChar(void) // Reads the next character from the RX Buffer { char temp = 0; if (rxByteCount > 0) // Return if nothing in the RX Buffer { temp = rxBuffer[rxOut]; // Save the character in the UART register clear_bit(pie1, RCIE); // Disable Rx interrupt rxOut++; // Point to next character in RX Buffer if (rxOut >= RX_BUFFER_SIZE) // If pointer is at the end of the buffer ... { rxOut = 0; // Put pointer back to start of buffer } rxByteCount--; // Decrement the number of bytes waiting to be read set_bit(pie1, RCIE); // Enable Rx interrupt } return temp; // Return the next character in the RX buffer } char getTxByteCount() // Returns the number of bytes in TX Buffer waiting to be sent { return txByteCount; } void putChar(char character) // Sets 7 bit EVEN Parity, puts a character in the TX Buffer and adjusts the pointers { delay_ms(1); // WHY ??? clear_bit(pie1,TXIE); // Disable Tx interrupt txBuffer[txIn] = Set_Parity(character); // set 7 bit EVEN parity and put in TX_In Buffer queue txIn++; // Increment pointer to TX_In Buffer if (txIn >= TX_BUFFER_SIZE) // Check to see if end of TX_In Buffer has been reached { txIn = 0; // If end of TX_In Buffer, then point to start of TX_In Buffer again } if (txByteCount < TX_BUFFER_SIZE) // If the TX_In Buffer isn't full ... { txByteCount++; // ... add 1 to the number of bytes in the queue } else // keep only the last {TX_BUFFER_SIZE} bytes { txOut++; // Increment the TX_Out Buffer pointer (overwrites a byte that has not been sent) if (txOut >= TX_BUFFER_SIZE) // If the pointer is at the end of the buffer ... { txOut = 0; // ... set it back to the beginning } } set_bit(pie1,TXIE); // Enable Tx interrupt } void sendString(const char * string) { char i = 0; // Point to first character in String while(string != 0x00) // Put all of String (except final 0x00) ... { putChar(string[i++]); // ... into TX_Out Buffer } } char Set_Parity(char character) // sets 7 bit EVEN parity // Parity bit (character.7) = 1 if there are an ODD number of 1s in the byte { character.7 = 0; // reset parity (8th) bit if (character.0) character ^= 0x80; // toggle parity bit if (character.1) character ^= 0x80; // toggle parity bit if (character.2) character ^= 0x80; // toggle parity bit if (character.3) character ^= 0x80; // toggle parity bit if (character.4) character ^= 0x80; // toggle parity bit if (character.5) character ^= 0x80; // toggle parity bit if (character.6) character ^= 0x80; // toggle parity bit return character; }
  10. Hi Pavel. I would like to see more info on PIC to PIC communications using I2C. I have designed a board to give me extra serial ports and I/O lines using a master and 2 PIC slaves, but I haven't got that part of the code working yet. Thanks, Danny
  11. Hi Rye. I keep getting my reply to your e-mail bounced. Here it is: Hi Rye. I haven't made any progress since June. This project has quite a few areas that need attention and I'm afraid that the I2C problem has been put to the back of the queue. I have finished the PIC processor board and 90% of the software is now running. The RF board is now complete and tested and so is the multi-port I/O board. I am just finishing the audio section this weekend. The next job will be the metalwork. I2C is a longer term goal to give me 2 additional hardware serial ports and a few more I/O ports from a couple of slave 876s (the main processor is the 18F4525). I don't need I2C to get the basic system working. Like you I am not a professional programmer and rely on help from the web or the forum to get me out of a hole when I am stuck. If I make any progress or find any useful sites I'll let you know. There seem to be quite a few people with the same slave problems. Its a pity that Microchip don't post more examples of slave operation using I2C. Best wishes, Danny
  12. Thanks Ettore. I've found various bits of code I can patch together to hopefully do what I need. Searching has also shown that there is an error in AN734 for Slave operation. Danny
  13. I have a board with 3 PICs, a master 18F4525 and 2 slave 16F876s, connected on the I2C bus. I wish to use the hardware UARTs on the slave PICs as additional serial ports (as well as additional I/O) using BoostC 6.70. I cannot search the archives for "I2C" (too few letters) and all of the examples I've found deal with reading/writing to an external EPROM. Can I get the master PIC to directly access the RAM locations in the slave PICs? Any help or pointers to example code would be most welcome as this is the last (I hope!) major function to be implemented in this long running project. Thanks, Danny Higgins
  14. The Hitachi display has 80 bytes of RAM. They are all accessible even if you don't have an 80 character display. You could try writing to / reading from one of the unused bytes to see if the display is there. Even if all 80 bytes are used you should be able to read a byte, change it, read it back again then set it back to its original value without noticing anything on the display. Danny
  15. Thanks Dave. I had just found that out. I knew I had added it before when I set up MPLAB with BoostC, but didn't realise I had to add it to every new project. Thanks, Danny
×
×
  • Create New...