Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Can TMR1 be used as a 16-bit shift register?

Status
Not open for further replies.

jpanhalt

Well-Known Member
Most Helpful Member
Just daydreaming here...

I am experimenting with the AMS AS5048 rotary encoder that outputs a 16-bit value using SPI. My MCU chip will be a Microchip enhanced mid-range device, such as the 12F1840 or 16F1519. Those devices have an MSSP serial port module, but it seems to be just 8-bits wide. I suspect I could clock the source (slave) relatively slowly compared to the MCU, detect a full buffer (SSP1BUF) and transfer that between clocks to get the full 16 bits without interruption.

I was just wondering whether TMR1's registers can be used as a 16-bit shift register rotating bits into it out of STATUS?

John
 
Not with timer1 registers... The timer will always increment... I was considering the gate control but that only disables the clock.... You would need to use the CCP module to detect if there is a pulse or not... The CCP can be tied to the comparator and the SR latch, so I'm sure there would be a way.....

I would stick a small routine in an interrupt and manually clock the data in using a set time clock...
What is the problem with using the SPI port.... If you control the CS pin yourself then read the SPI twice in succession you will get all 16 bits..

My next tutorial is an SPI implementation using a 10 bit ADC and a 12 bit DAC... Both will use a full 16 bit transfer...
 
Thanks, Ian.

Useful comments. I was just simulating it and found that rotating TMR1L left goes to STATUS, not TMR1H. Of course, I can rotate TRM1H too, but that is just like using two, 8-bit registers. That's why they are called daydreams, I guess.

Anyway, I can set the clock to the source (slave) at 1:4 or 1:16 relative to the system clock. I haven't written any code yet, but if 1:4 isn't long enough, then 1:16 will be more than adequate to use the MSSP module and the SSP1BUF. That is, do what you suggest in your second paragraph. With my oscillator at 16 MHz, I am sure I won't notice any difference between 1:4 and 1:16.

John
 
Once again! Why can you not just use the SPI module?? 16bit transfers are quite easy to implement!!

The interrupt routine ( I was suggesting ) is to run side by side with the comparitor... Using the timer1 for the synchronous clock and the comparator input to shift in all 16 bits at once.... It would be too messy though!! The MSSP is really the only way to go...
 
Once again! Why can you not just use the SPI module?? 16bit transfers are quite easy to implement!!

That is what I mean to do. (NB: I edited my post. You may have missed it.) I will be using the MSSP/SPI module. Moving the 8-bit buffer into a pair of temp registers is no big deal. I was just wondering whether the TMR1 registers roll over to each other when not used as counters.

John
 
That is what I mean to do. (NB: I edited my post. You may have missed it.) I will be using the MSSP/SPI module. Moving the 8-bit buffer into a pair of temp registers is no big deal. I was just wondering whether the TMR1 registers roll over to each other when not used as counters.

John
I keep forgetting you use ASM... The 16 bit timer would have been a good idea if it were possible..

However!! C compiles to ASM so it must be quite easy..
 
I was just setting up a simulation sending 0x5555 as my stimulus. I am starting with a slow clock to the SPI slave and keeping MOSI high (my sensor allows that), so the timing should be quite easy to figure out.

OT: It is a gorgeous day, and I should be working on the farm. Got things greased yesterday and fixed the glow plug heater/timer on the tractor, so it starts. Unfortunately, we had a lot of rain last week and the ground is too soft to drive anything on. Around 3PM today, I will have to knock off to set up a sprayer for some carpenter bee poison. Will then start spraying the house (log cabin) once the wind dies down. So, I have a few hours to play with it until then.

John
 
OT: It is a gorgeous day, and I should be working on the farm. Got things greased yesterday and fixed the glow plug heater/timer on the tractor, so it starts. Unfortunately, we had a lot of rain last week and the ground is too soft to drive anything on. Around 3PM today, I will have to knock off to set up a sprayer for some carpenter bee poison. Will then start spraying the house (log cabin) once the wind dies down. So, I have a few hours to play with it until then.
It was forecast here "Mainly Sunny".... Guess what! They couldn't have been more wrong!!
 
It is sunny here. But the ground is still frozen and hard as a rock.

With MSSP, you don't need to slow down clock to SPI slave. Since you're the master, you set the pace, and you can go as fast as your sensor can send. It is Ok to have a large time gap between two 8-bit values to successfully receive 16-bit value from the slave.
 
This is from the datasheet:
The SPI is active as soon as CSn is pulled low. The AS5048A then reads the digital value on the MOSI(master out
slave in) input with every falling edge of CLK and writes on its MISO (master in slave out) output with the rising edge. After 16
clock cycles CSn has to be set back to a high status in order to reset some parts of the interface core.

This is my first experience with SPI. The two MSB of the 16-bit value at parity and error bits. I was worried that interrupting the transmission using CS and MOSI might end up transmitting parts of two different 16-bit values. That is, I don't understand how the data are buffered in the device. However, slowing the clock or stretching a pulse after the first 8 bits seemed like it would be less likely to corrupt the data. The thing is so fast compared to what I have been using, that simply running the clock slower to allow reading the SSPBUF would be least likely to cause problems and wouldn't be noticed in my application. Will give it a fresh start the next rainy day. BTW, I am just holding MOSI high.

I spent the day trying to simulate a program to get a flag bit, then discovered that function is probably not supported by MPLAB SIM. I am beginning to think one should just count the clock cycles (edited: originally, "bits") received.

Thank you for the advice.

John
 
Last edited:
It doesn't appear that the SPI ports can be configured for any number of bits. It would be nice if you could set it up for say 14 bits. A few weeks ago, I was interfacing a PIC to an Avago 12 bit encoder, and thought maybe I could use SPI, but the encoder had a data length of 12 bits plus a start and stop bit. If you gave it 16 clock pulses, then it would interpret the last two clock pulses as the start of the next read operation, and then things would get screwed up. Eventually, I decided that the easiest solution was to bit bang the data in, in a program loop.
Code:
; Encoder SSI read routine
    bank0
    movlw d'12' ; bit count
    movwf count
    bsf portA,EncClk ; start with clock high
    bcf intcon,gie    ; disable interrupts during read
    bcf portA,EncCS ; clear SSI chip select to init read
    bcf portA,EncClk ; set clock low
    goto $+1 ;this is a 2 cycle nop
    nop
    bsf portA,EncClk ; set clock high for 4 cycles
    goto $+1
    nop ;the above toggle discards the start bit
SSIreadloop
    bcf portA,EncClk ; set clock low for 4 cycles
    rrf portA,w ; read data bit (portA.0) by rotating it into carry bit
    rlf psnL,f  ; and shift into position register
    rlf psnH,f
    bsf portA,EncClk ; set clock high for 4 cycles
    decfsz count,f
    goto SSIreadloop
    bsf portA,EncCS ;set chip select high
    movlw 0x0F
    andwf psnH,f    ;Clear any extraneous high bits
    bsf intcon,gie    ; re-enable interrupts
 
Last edited:
I don't think MSSP buffers data. SPI is very different from UART.

You can do as follows:

- enable MSSP in the master SPI mode
- clear SPI1IF
- pull CS low
- write the high byte of 16-bit value you want to send to SPIBUF (write 0 if you only want to receive)
- wait for SPI1IF to be set and then clear it
- read the high byte of the value you're receiving from SPIBUF
- write the low byte of 16-bit value you want to send to SPIBUF (0 if receive only)
- wait for SPI1IF to be set
- read the low byte from SPIBUF

At this point you have exchanged 16-bit values - sent one, received one. Both sending and reception happens at the same time. SPI is always full duplex.

More often than not, the SPI communication protocols are such that you either send or receive at any given time. But with SPI you still need to do both. If you want to send only, you still must read - discrad the values read from SPIBUF. If you want to receive only, you still must write - write zeroes.
 
Thank you both. I will try those things next chance I get. I did spend quite a bit of time trying simulations to get the SSPIF flag, including register injection, with no success. May just have to try it blind or try in-circuit debugging and live with very limited breakpoints.

John
 
UPDATE:
I spent 2 days convincing myself that MPLab SIM would not simulate the SPIIF flag (PIR1, SSPIF) properly. So, I have rigged everything up on a breadboard to use the ICD3 and real devices. My MCU is the 16F1519, which will allow 3 hardware interrupts.

Two question, which are probably obvious, but I could not find explicit answers in the datasheet:
1) Reference is made to starting and stopping the SPI clock, but there is no clock enable bit, like there is, for example, with TMR1. Does one simply use the SPI enable bit?
2) My sensor device (AS5048) describes a 3-wire configuration with its MOSI input pin tied high. Can the MOSI output pin of the MCU ("SDO", RC5) just be set high too? My guess is that will not work, and one still needs to load the SSPBUF register and send it, even if the pins are not connected.

Thanks again.

John
 
The module starts/stops the clock automatically. Every time you send a byte, it'll produce 8 clock pulses.

There is a thing called "framed SPI" where clock runs continuously and master marks the bytes with pulses on SS line. I don't think MSSP would support this.

If you tie MOSI high you won't be able to send anything, only receive. If that's what you want, simply declare SDO as an input (TRIS bit high) and do not connect it to anything. You can even use as a GP input for some unrelated task. Then connect sensor's MOSI to VDD. Even if you don't use SDO/MOSI, you still need to write to SPIBUF. Otherwise, you won't get any clock.
 
Thank you. The sensor (slave) has OTP configuration fuses. Sending 0xFF or tying its input high would avoid accidentally sending a configuration command until I am comfortable with how it works. After much more reading on SDI, I suspected that I still had to send something from the master to get the peripheral to work. Thanks for confirming that and for suggesting the best way to do it. Microchip also recommends just turning the output port off by setting TRIS high.

I was all set to try it, but had a bit of an accident around noon (it is now 3:45 in Cleveland). I was finishing up spraying for carpenter bees, and when I got on the ladder to get off the roof, the ladder collapsed. In all my years of using extension ladders, that is the first time I did not visually check the latches. No damage to back or head, but I probably cracked or severely bruised some ribs when I landed on top of the ladder rail. I will be stuck in a chair probably most of the night, since the pain from lying down is too great. Maybe I can try it tonight; otherwise, it is an unwanted break in that fun.

John
 
I am doing my best. My 50th reunion from college begins Friday and includes a lacrosse game on Saturday against U. Michigan. I have been looking forward to it for 6 months. Right now, I can't drive, but I think a good part of the pain/disability is muscle spasm. Tomorrow will be the test.

I hope you have been well.

John
 
Not quite whole yet, but I have been playing with the SPI using ICSP and in-circuit debugging with my ICD3 when I can.*

I put in a couple of breakpoints (one at start of the routine and one for error). A few errors did pop up occasionally, but I am not surprised as the AS5048 sender is not really synced with the MCU. I am quite happy with the data. Here are the raw counts for three knob positions for the magnet over the AS5048:

upload_2015-4-24_14-32-19.png


I am still fine tuning some of the code.

John

*Edit: Sorry. Forgot to update here. Broke 5 ribs, some in more than one place. Had a pneumo/hemo thorax (collapsed lung). Spent almost a week in the hospital with a chest tube. Doing much better now.
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top