# [SOLVED]UART on PIC16F1618, PIC16F690, PIC16F1708

Status
Not open for further replies.

#### jsbhalla88

##### Member level 1
hi
I am trying to get the hardware UART working on PIC16F1618 @ 8MHz, 9600bps.

I have worked on hardware uart earlier with other PIC controllers. but I am not able to get this one working.
when I use the UART library routines, it gives the following error:
"Unresolved extern 'PPS_Mapping' __Lib_UART_Remappable.c"

if I use the library function: Unlock_IOLOCK();
to remap the pins, it gives an error again, saying, "Undeclared identifier 'Unlock_IOLOCK' in expression MyProject.c" refreing to the line where I had used this function.
I have selected all libraries.

So, I tried remappable UART library functions.
it did not give any errors, but it did not work either.
it did not receive, nor transmit anything. data is transmitted from PC to Rx pin, but does nothing. I have checked with oscilloscope
program is working, not stuck, as I had put in code to toggle an output every cycle, and the output was toggling turning the LED on/OFF.
I have disabled the analog function for Rx pin, set the Rx pin as input, and Tx pin as output.
it does not transmit anything,
cannot REMAP pins until Unlock_IOLOCK(); and other mapping functions work.
software UART is working, but I need hardware UART for my application.

thanks..

#### bigdogguru

##### Administrator
Please post your code using either CODE or SYNTAX tags or zip up your project and upload it using the Manage Attachments feature, so that we can examine it.

#### betwixt

##### Super Moderator
Staff member
Do those PICs have PPS mapping?

Brian.

#### jsbhalla88

##### Member level 1
sorry, I don't have that code now as I have made lots of changes in my code since then..,
now I am working on PIC16F1708.
it has remappable pins and functions as well., but I don't know how to use those functions., they are predefined in PIC library..i am working on MikroC for PIC, by MikroElektronika..
does anyone know how it works..??
Code:
void main ()
{
ANSELB = 0;           // disable analog function on port B

TRISB.B5 = 1;         // Rx pin as  input
TRISB.B7 = 0;        // Tx pin as output
// remappable funciton
Unlock_IOLOCK();
PPS_Mapping(10, _OUTPUT, _TX_CK);
Lock_IOLOCK();
UART1_Init(9600);

// for blinking LED
ANSELC = 0;
TRISC = 0;
LATC = 0;
while(1)
{
UART1_Remappable_Write_Text("Hello\n");
Delay_ms(1000);
UART1_Write_Text("Hello\n");
Delay_ms(1000);
UART_Write_Text("Hello\n");
Delay_ms(1000);
blink();

}
}

blink() function is blinking an LED on pin RC7.
I have tried all write functions. its not giving any errors, but its not working.

any suggestions..??

#### betwixt

##### Super Moderator
Staff member
PPS Mapping simply assigns a peripheral input or output to the specified 'RP' pin.

The complication is that the data sheet doesn't refer to the pins by their remapping number but MikroC does. You are mapping pin RP10 to output the USART clock so I assume you are using it in synchronous mode.

I suggest you ignore the MikroC instruction and code the PPS manually, it would be far easier!

Brian.

jsbhalla88

### jsbhalla88

Points: 2
Helpful Answer Positive Rating

#### jsbhalla88

##### Member level 1
I have not used the peripheral select option as I don't know how to use it.,.
i have looked at the data sheet, but, didn't understand much about.., how to implement it..??

#### Aussie Susan

##### Advanced Member level 4
First off, the power on default is for the PPS registers to be unlocked. However, the power on default for PPS1WAY is to not allow the PPSLOCK to be altered after it has been set. Therefore I strongly suggest that you leave the locking and unlocking right out of your code until you have gained experience with the device and your code - in other words this should be one of the last aspects of your code that you add.
Section 12 of the data sheet is relatively straight forward once you get the hang of how the PPS works and Figure 12-1 will help you there. In your case you want to use the Register 12-2 and Register 12-3 descriptions.
You want to use the EUSART (and I assume in asynchronous mode) and so you will be interested in mapping the Tx signal to an output pin and the Rx signal to an input pin.
If you look at Table 29-8, you will see a register labelled RXPPS listed. This is the register you need to set to a value to select the Rx single pin. Lets say you want this to be RA5. Looking at Register 12-2, you will see that RA5 has a value of 0b00101, so you will use
Code:
RXPPS = 0b00101;
Table 29-8 also lists a register called RxyPPS which is used to select the pin for the Tx signal. Register 12-3 shows that the value for Tx is 0b10100 so to map that signal to RA4 (as an example) you would use
Code:
RA4PPS = 0b10100;
Susan

jsbhalla88

### jsbhalla88

Points: 2
Helpful Answer Positive Rating

#### jsbhalla88

##### Member level 1
thanks a tonn Susan., I just added
RB7PPS = 0b10100;
RXPPS = 0b01101;
it worked..
I have one more doubt., data sheet says that you have to follow a sequence to lock/unlock peripheral select., sequence is given in assembly in data sheet(page 140).
I have not used that sequence, nor did I change anything in PPSLOCK register.
I did not use it, code works fine...
my question is, do I need to use unlock and lock sequence..??

#### jsbhalla88

##### Member level 1
for I2C,
SSPCLKPPS = 0b11100; // RB6 as SCL
SSPDATPPS = 0b01100; // RB4 as SDA
OR ,
RB6PPS = 0b10000;
RB4PPS = 0b10001;

did I write any of them correctly or not..????

Last edited:

#### Aussie Susan

##### Advanced Member level 4
I have actually answered your question about the need to use the unlock sequence at the top of my last post. For your device (and most Microchip MCUs from my experience) the unlock sequence is NOT required so long as you leave the power-on configuration bits in their default state. However, you do need to read the data sheets for each and every device you use to make sure about this.
Personally, I like to leave the PPSLOCK (or whatever it is called for any device) in the unlock state and also make sure that the PPS1WAY (or equivalent) setting allows the locking and unlocking of the PPS registers as many times as you want.
Only when you get to the end of your project and you are sure that you have the PPS settings such that they will not be altered again, should you look to lock the PPS registers.
I must confess that I've not used the I2C peripheral at all with a device that has PPS, but if I remember correctly, the SDA and SCL lines are bi-directional. Looking at the data sheet, and in particular Note 2 on page 283, you need to connect the signal and the pin as both input and output.
However I think you have some values set incorrectly above. Looking at the data sheet tbales and register descriptions, I think you will need:
Code:
SSPCLKPPS = 0b01110;  // RB6 input to SCL  << Note the difference to your value
SSPDATPPS = 0b01100; // RB4 input to SDA
RB6PPS = 0b10000;       // SCL output to RB6
RB4PPS = 0b10001;       // SDA output to RB4
[\code]
Susan

jsbhalla88

### jsbhalla88

Points: 2
Helpful Answer Positive Rating

#### jsbhalla88

##### Member level 1
SSPCLKPPS = 0b01110; // RB6 input to SCL
SSPDATPPS = 0b01100; // RB4 input to SDA
RB6PPS = 0b10000; // SCL output to RB6
RB4PPS = 0b10001; // SDA output to RB4
i missed that note earlier, thanks for pointing out...
i have to write all the 4 lines ????
i got the point that these pins are bidirectional...what is the difference between 2 lines which i had written to 4 lines you have..??? will it configure the same pin RB4 as input as well as output for SDA..???
wont the last be over write the first line for RB4..???
i might be asking some very basic questions, but i dont know anything how to use the same pin as input as well as output..

and one more thing, if you can help, i have been using all built in library functions for SOFTWARE UART, I2C, SOFTWARE I2C etc., for all other peripherals.,, except from hardware UART,... where should i start from if i need to write my own routines for all these..?? is there a sample code...??
Thank you for pointing out my mistakes..

Last edited:

#### Aussie Susan

##### Advanced Member level 4
Yes - all 4 lines.
If you look at the data sheet and the diagram at the start of the PPS section, you will see that there are 2 types of mapping: from the pin to the device for 'input' signals, and from the device to the pin for output signals. Therefore you need to set the mapping for both the input and output aspects of both pins - hence 4 lines of code.
You will also see notes in that section that the peripheral also controls the TRIS lines for the selected pins so that it can handle the switching from input to output for lines such as SDA and SCK.
As for writing library functions for the various peripherals, I personally think this is over rated, especially for peripherals that are as straight forward as UARTs and SPIs. The initialisation code takes a few lines to write but is typically only executed once - and also give you a great place to put comments on what the configuration is supposed to be and why (if there are special characteristics that need to be considered). Sending and receiving values is generally very straight forward BUT the characteristics you want to use (e.g. interrupt driven vs poling/blocking, use of circulars buffers etc.) can be very situation specific and I find library functions often hide important characteristics that mean I spend hours tracking down strange behaviors.
Exceptions (for me) are TCP/IP and USB interfaces where I always use the library functions as the complexities of using these peripherals is high.
Also, my experience is that library functions really do not move well from one device to another, in particular between device families. Also, the code required for embedded applications tends to be specific to that application and you often want to get the best performance out of the limited CPU clock speed and memory - and library functions need not provide either.
Susan

#### betwixt

##### Super Moderator
Staff member
Adding to what Susan stated, and this is entirely a personal opinion, MikroC has lots of serial functions that do very little.

Setting up something like a USART is actually very easy, there are only a few registers and it probably takes fewer lines of code to do it yourself than using the library. You also get the benefit of absolute control instead of predetermined conditions being imposed. The key is to thoroughly read and understand the data sheets and understand how the peripheral actually works, all the information you need is there.

Your particular problem with remappable pins is due to MikroC using different names to Microchip for the pins. The numbers MikroC uses are for the PIC18 devices which call them 'RPxx' in the data sheets but the PIC16 devices refer to them only by port names. Perhaps Mikro will change this in the future but for now I would code the mapping instructions by hand as Susan and I have explained.

Brian.

#### jsbhalla88

##### Member level 1
I have written hardware UART code myself.., without using library functions. I don't know how to write it for software UART, software I2C.., I understand the concept for UART, but I don't understand how would you generate the output to send data ..?? would I need a timer which can generate the baud rate..??? how would I make equivalent of the timing diagram though my code..??
for example, if I get high signal on one of the pins, how would I generate the CLK signal delay for milliseconds, or how would I toggle the output at such high speed to transmit ASCII and how would I store the ASCII received to make meaningful characters..??
I have read online articles for software UART, but they don't clear my doubts..

thank you Susan and Betwixt.
I will try I2C configuration today..

#### milan.rajik

##### Banned
Doesn't mikroC has Soft_I2C and Soft_UART library ?

#### betwixt

##### Super Moderator
Staff member
Doesn't mikroC has Soft_I2C and Soft_UART library ?

It probably does but in this case things are complicated by the use of remappable pins.

The principle for 'bit banging' serial transmission is to use a timer to set the bit rate, at each timer tick you shift the data (rrf, rlf) and check the MSB or carry flag, copying it's state to the appropriate output pin. You preceed the first bit with a 1-bit long start bit and at the end you add a 1-bit long stop bit.

Reception is similar but you have to cater for the start bit in a special way. You monitor the input pin for the leading edge of the start bit, wait 1.5 bit lengths then sample 8 times at 1-bit length intervals. The idea is that if you wait 1.5 bits length, the next sample will be at half way through the first data bit which is the most reliable place to test it. You repeat the sampling 8 times, rotating the pin state into a register. The serial data should then be in that register for you to use.

A 'real' UART/USART does exactly the same thing but uses several samples per bit and a majority polling algorithm to improve reliability, it may also check the stop bit and parity if necessary.

This is code I wrote for bit banging a serial link to a HITAG module, it's in assembly language for a 16F628A but you can see the methods I used.
Code:
;**********************************************************************
; software UART sends bytes to HITAG at 9600 bauds
HitagSend
bsf	HWStatus,TXingToHitag
movwf	HitagShiftReg		;save byte in Shift Register
movlw	0x09			;number of bits including start bit
movwf	HitagBitCount
bcf	STATUS,C		;low for start bit
H_BitLoop
btfsc	STATUS,C		;output bit in carry flag
bsf	DATA_TO_HITAG
btfss	STATUS,C
bcf	DATA_TO_HITAG
call	H_1BitDelay		;delay for 104.17uS (bit length at 9600 Bauds)
rrf	HitagShiftReg,f
decfsz	HitagBitCount,f		;see if all bits are sent
goto	H_BitLoop
bsf	DATA_TO_HITAG		;high for stop bit...
call	H_1BitDelay		;...for at least one bit
bcf	HWStatus,RXingFromHitag
return

;**********************************************************************
; delay routines to pace the software UART
H_05BitDelay
movlw	0x3A			;half bit delay
movwf	HitagBitDelay
goto	H_Delay1
H_1BitDelay
movlw	0x75			;1 bit delay
movwf	HitagBitDelay
H_Delay1
clrwdt
decfsz	HitagBitDelay,f
goto	H_Delay1
return

;**********************************************************************
; waits for one byte of data from the HITAG and returns it in W
HitagRx
clrwdt
btfsc	DATA_FROM_HITAG		;wait for start bit
goto	HitagRx
movlw	0x08			;bits to receive
movwf	HitagBitCount
clrf	HitagShiftReg
call	H_05BitDelay		;align to centre of first bit
H_Rx1
call	H_1BitDelay		;wait for centre of bit
bcf	STATUS,C
btfsc	DATA_FROM_HITAG
bsf	STATUS,C
goto	H_RxShift		;bit was a zero
H_RxShift
rrf	HitagShiftReg,f		;rotate bit into shift register
decfsz	HitagBitCount,f
goto	H_Rx1			;if more bits to sample
movf	HitagShiftReg,W
H_RxEnd
clrwdt
btfss	DATA_FROM_HITAG		;must end with data line high (stop bit)
goto	H_RxEnd
return

'DATA_TO_HITAG' is the serial output pin and 'DATA_FROM_HITAG' is the serial input pin.

Brian.

#### jsbhalla88

##### Member level 1
Doesn't mikroC has Soft_I2C and Soft_UART library ?

yes they have libraries. BUT, I want to know the logic and steps to write my own routine for software I2C and UART. What if I have to work on some new IDE, or different microcontroller?? I will again have these doubts to ask..so better try to do this now..
Thanks..

- - - Updated - - -

BETWIXT:
thank you for the code., but I am not good at all with assembly. still, I will try it..
it will really great if you have the same code written in C..??

Thanks and Regards
Jaskaran Singh

#### betwixt

##### Super Moderator
Staff member
Start with the data sheet, look for timing diagrams, the ones that show lines in high, low or 'don't care' logic states. Then refer to the tables showing the rise times, fall times and bit lengths. Where you see a line driven high, you write an instruction to make the level on a pin go high, when a line is driven low, you make the pin low. If there is a time restriction you add a suitable delay. For accepting incoming signals you do exactly the same thing only this time you use the timing to read the state of a pin. The length of the data in bits is set by using a suitable loop in your code. You can usually use a register a 'shift register' to serialize the data, you load it with the value to send and rotate it say 8 times, checking the carry bit to see if you should send a 1 or 0 in the data. For reception, you read the pin and rotate it's state into a register until it is all there then read it as normal. It's quite easy, just follow the flow shown in the diagrams.

Brian.

Status
Not open for further replies.

Replies
7
Views
9K
Replies
1
Views
2K
Replies
6
Views
5K
Replies
2
Views
1K
Replies
0
Views
1K