Attiny204 Interrupt Flag Not Being Generated - interrupt

I'm trying to write a (fairly) basic bit of software for and Attiny204, which handles interrupts when a clock input is pulled high.
When I run the code in the debug simulator in Atmel Studio, and set the clock input high, there is no interrupt flag generated. The interrupts do trigger when I manually produce an interrupt flag.
I've tried using different pins, and even, the other port. I can't seem to get the simulator to produce the interrupt flag.
In the past, I have used the AtMega328P in the simulator with equivalent code, and it works fine.
ISR(PORTA_PORT_vect)
{
//In this function we must:
//1. Shift all data up
shiftUp();
//2. Get new 8th bit
bit8 = VPORTA.IN & (1 << 1);
//3. Set Data Output Pin to bit0
if(bit0 == 0)
VPORTA.OUT &= ~(1 << 3);
else
VPORTA.OUT |= (1 << 3);
//4. Calculate new dimValue and dimMilliseconds
calcDim();
calcDelay();
}
int main(void)
{
initVariables();
/*
Below this, we must set the Data Direction (DD) of each pin we assigned.
*/
//Below, set the ISC of the Zero Cross Pin and the Clock Pin to allow interrupts
PORTA_PIN0CTRL |= 0b00000001; //Zero Cross
//PORTA_PIN1CTRL = 0b00000000; //Data In
//PORTA_PIN2CTRL = 0b00000000; //Data Next
//PORTA_PIN3CTRL = 0b00000000; //Triac Control
PORTB_PIN0CTRL |= 0b00000001; //Clock
//VPORTB.INTFLAGS |= 0b00000001;
//Set Port direction.
VPORTA.DIR = 0x30;
VPORTB.DIR = 0x00;
/*
Below this, we must enable interrupts.
*/
sei();
/* Replace with your application code */
while (1)
{
}
}

Why are you writing to VPORTA and VPORTB? The Tiny204 doesn´t have this registers.
You enable interrupts on both edges for Pin 0 of Port A (PIN0CTRL bit 0 is set = BOTHEDGES) and you don´t clear the interrupt flag in your ISR of Port A. Please take a look at the data sheet:
The interrupt request remains active until the interrupt flag is cleared. See the peripheral's INTFLAGSregister for details on how to clear interrupt flags.

Related

STM32F7, Bare Metal C, QSPI Indirect Mode Hangs or Writes Same Gibberish

Win 10, STM32CubeIDE 1.8.0
STM32F746 Discovery board
MCU: STM32F746 (Datasheet, Reference Manual, Errata)
Flash: MT25QL128ABA1EW9-0SIT (Datasheet)
Equipment: Low end oscilloscope, low end logic analyzer with decoder
What I'm trying to achieve: I want to be able to send command via indirect write (works OK), read register with indirect read (fails miserably with consistent garbage on the lines), haven't even tried to read/write actual memory.
Connections (from the discovery board schematic):
Interestingly enough, the example provided by STMicoelectronics themselves also doesn't work as expected. More on that later.
Initially, I read the reference manual and tried to figure the stuff out on my own, as I always do when I learn to operate new peripheral. It didn't exactly work out, so I used TouchGFX-generated code to compare configuration (it's using memory mapped mode, but I could at least check clock and GPIO setup, and it was correct), then I also found pretty much the only other article that does what I do. I was close, but a few unexplained (not covered in reference manual) bits from the article made it work. (Article)
I used only the early code from there. Up to and including the first bit of code under "Initialization" section, but not anything further. I adjusted it for my Flash size (128Mbit).
I will safely assume my clock and GPIO initialization is correct, as it matches TouchGFX code, which utilizes QSPI Flash, as well as example program from STM32F7 package.
I'm configuring QSPI with 1MHz clock. While it's not exactly covered in specs of the Flash IC, it's easier on my scope and logic analyzer, both of which have 100MHz as documented upper bound, but they're not really usable there. I also tried to use 108MHz, which is a documented Flash IC spec, I still get garbage there (found via debugging output).
QSPI setup:
void qspi_setup_indirect_mode(void) {
/* ------------ QSPI Initialization --------------- */
/*
* Make sure QSPI is disabled
* */
QUADSPI->CR &= ~(QUADSPI_CR_EN);
/*
* Flash size 128Mb=16MB=2^24 bytes
* 24-bit Address
*
* */
QUADSPI->DCR = 0x00; //reset
QUADSPI->CCR = 0x00; //reset
QUADSPI->DCR |= (23U << QUADSPI_DCR_FSIZE_Pos);
QUADSPI->CCR |= (2U << QUADSPI_CCR_ADSIZE_Pos);
/*
* Sample shift 1/2 clock cycle
* Prescaler = 2 (216MHz/216 = 1MHz)
*
* */
QUADSPI->CR = 0x00; //reset
QUADSPI->CR |= (QUADSPI_CR_SSHIFT | (215U << QUADSPI_CR_PRESCALER_Pos));
/*
* Make sure all flags are cleared
*
* */
QUADSPI->FCR = QUADSPI_FCR_CTOF | QUADSPI_FCR_CSMF | QUADSPI_FCR_CTCF | QUADSPI_FCR_CTEF;
/*
* Enable peripheral
* */
//QUADSPI->CR |= (QUADSPI_CR_EN); (enable later for every transmission)
}
Then there is function, that sets command mode. It sets access mode (indirect write, read, polling, memory mapped), as well as on how many datalines instruction, address and so on are transmitted (from none to 4), and dummy cycles. Nothing fancy, very similar to the one from the example.
void qspi_set_command_mode(uint8_t fmode, uint8_t imode, uint8_t admode, uint8_t abmode, uint8_t dcyc, uint8_t dmode) {
/*
* Make sure QSPI is disabled
* */
QUADSPI->CR &= ~(QUADSPI_CR_EN);
/*
* Communication configuration register
* First, reset all mode values
* Set new values
* */
QUADSPI->CCR = QUADSPI->CCR & ~(QUADSPI_CCR_FMODE) & ~(QUADSPI_CCR_IMODE) & ~(QUADSPI_CCR_ADMODE) & ~(QUADSPI_CCR_ABMODE) & ~(QUADSPI_CCR_DCYC)
& ~(QUADSPI_CCR_DMODE);
QUADSPI->CCR = QUADSPI->CCR | (fmode << QUADSPI_CCR_FMODE_Pos) | (imode << QUADSPI_CCR_IMODE_Pos) | (admode << QUADSPI_CCR_ADMODE_Pos)
| (abmode << QUADSPI_CCR_ABMODE_Pos) | (dcyc << QUADSPI_CCR_DCYC_Pos) | (dmode << QUADSPI_CCR_DMODE_Pos);
}
I tried various minor changes to these functions, and write works if and only if I disable peripheral, configure the thing, enable, set the instruction. If I enable peripheral in the setup section, write doesn't work. This is not covered in reference manual, I found it in the article (where it's not pointed out).
void qspi_sendCommandIndirectWrite(uint8_t command) {
QUADSPI->CR &= ~(QUADSPI_CR_EN); //disable qspi to configure
QUADSPI->FCR = QUADSPI_FCR_CTOF | QUADSPI_FCR_CSMF | QUADSPI_FCR_CTCF | QUADSPI_FCR_CTEF; //clear all flags
qspi_set_command_mode(0x00, 0x01, 0x00, 0x00, 0x00, 0x00); //Set indirect write, only instruction on 1 line, everything else off
QUADSPI->CCR &= ~(0xFF << QUADSPI_CCR_INSTRUCTION_Pos); //clear instruction field
QUADSPI->CR |= (QUADSPI_CR_EN);
QUADSPI->CCR |= (command << QUADSPI_CCR_INSTRUCTION_Pos); //writing instruction starts communication
while (QUADSPI->SR & QUADSPI_SR_BUSY); // Wait for the transaction to complete, and disable the peripheral.
QUADSPI->CR &= ~(QUADSPI_CR_EN);
}
void qspi_sendCommandIndirectRead(uint8_t command, uint8_t receiveBuffer[], uint32_t length) {
QUADSPI->CR &= ~(QUADSPI_CR_EN); //disable qspi to configure
QUADSPI->FCR = QUADSPI_FCR_CTOF | QUADSPI_FCR_CSMF | QUADSPI_FCR_CTCF | QUADSPI_FCR_CTEF; //clear all flags
qspi_set_command_mode(0x01, 0x01, 0x00, 0x00, 0x01, 0x01); //Set indirect write, only instruction on 1 line, , data on 1 line, 1 dummy cycle, everything else off
QUADSPI->CCR &= ~(0xFF << QUADSPI_CCR_INSTRUCTION_Pos); //clear instruction field
QUADSPI->DLR = length;
QUADSPI->CR |= (QUADSPI_CR_EN);
QUADSPI->CCR |= (command << QUADSPI_CCR_INSTRUCTION_Pos); //writing instruction starts communication
uint32_t counter = 0x00;
while (counter < length) {
while (!(QUADSPI->SR & QUADSPI_SR_TCF)); //wait while data arrives to FIFO
receiveBuffer[counter] = (uint8_t) (0xFF & QUADSPI->DR);
counter++;
}
while (QUADSPI->SR & QUADSPI_SR_BUSY); // Wait for the transaction to complete, and disable the peripheral.
QUADSPI->CR &= ~(QUADSPI_CR_EN);
}
Finally, all of that is called in the main the following way:
#include "main.h"
void system_hw_setup(void);
void qspi_example(void);
int main(void) {
system_hw_setup(); //initialize hardware
system_msdelay(100U);
//qspi_sendCommandIndirectWrite(MT25QL128ABA1EW9_COMMAND_ENTER_QUAD_IO_MODE); //works OK
//qspi_example(); //example provided by STM32 w clock and GPIO setup
system_msdelay(100U);
uint8_t test[1];
while (1) {
qspi_sendCommandIndirectRead(MT25QL128ABA1EW9_COMMAND_READ_STATUS_REGISTER, test, 1);
//qspi_sendCommandIndirectRead(MT25QL128ABA1EW9_COMMAND_READ_ENHANCED_VOLATILE_CONFIGURATION_REGISTER, test, 1);
system_msdelay(100U);
toggle_stm32f746disco_ld1();
/*
test[0] = 0x00;
if (test[0] == 0x00) {
test[0] = (uint8_t) '0';
}
/usart_dma_sendArray(USART1, test, 1); */
}
}
void system_hw_setup(void) {
rcc_setup(); //clock for peripheral, clock will not be altered; therefore default HSI 16MHz
systick_setup(SYSTEM_FREQUENCY); //activate systick
gpio_setup(); //set pin modes and functions
dma_reset_flags(DMA2); //clear DMA2 flags for USART1
dma_reset_flags(DMA1); //clear DMA1 flags for I2C3
usart_dma_setup(USART1); //set control registers and settings for USART1 and its DMA connected to st-link
usart_enable(USART1); //enable uart1
usart_enable_tx(USART1); //enable tx line (wrapper)
usart_enable_rx(USART1); //enable rx line (wrapper)
qspi_setup_indirect_mode(); //enable qspi in indirect mode
nvic_setup(); //set interrupts and their priorities
}
which gives the following:
As per reference manual, data from the IC should come on DQ1, but it's not happening. Also, sometimes DQ3 randomly goes up for some time. The number of clock cycles is strange. Also, I have no idea why there is some 0x80 packet there, I'm sending only the instruction and nothing else. It could be related to my artificially lowered clock speed, but the same configuration also miserably fails if I set QSPI clock to proper value.
I'm pretty lost at what I'm doing wrong, and the reference manual section of the MCU is not much help at this point, and there are next to no resources on the internet that cover it in a meaningful (or any, at this point) way.
I would appreciate any help or advice with making QSPI work!
The main problem was the access to data register. QUADSPI->DR is a volatile uint32_t. So whenever I access QUADSPI->DR, even if I received 1 byte, it reads 4 bytes from the register, and it also produces gibberish with FIFO threshold because of that. The correct solution is to explicitly specify byte, half-word or word access to the QUADSPI->DR. I take address of the data register, cast it as a pointer to uint8_t or uint16_t, and dereference it:
uint32_t mydata = QUADSPI->DR;
uint16_t mydata = *(uint16_t*)(&QUADSPI->DR);
uint8_t mydata = *(uint8_t*)(&QUADSPI->DR);

ATMEGA2561 WINC1500 Driver implementation SPI problem

I am trying to implement the WINC1500 MLA Driver to work with the ATMEGA2561 MCU and I have written my driver code and it's stuck on the line "while((SPSR & (1 << SPIF)) == 0);" in the m2mStub_SpiTxRx function.
I have no idea why it's not progressing through. I'm using the jumpstart ImageCraft IDE for this project.
Here's the implementation of it
void m2mStub_SpiTxRx(uint8_t *p_txBuf,
uint16_t txLen,
uint8_t *p_rxBuf,
uint16_t rxLen)
{
uint16_t byteCount;
uint16_t i;
// Calculate the number of clock cycles necessary, this implies a full-duplex SPI.
byteCount = (txLen >= rxLen) ? txLen : rxLen;
DEBUGOUTF("Calculate the number of clock cycles\n");
DEBUGOUTF("byteCount %d", byteCount, "\n");
DEBUGOUTF("txLen %d", txLen, "\n");
DEBUGOUTF("rxLen %d", rxLen, "\n");
// Read / Transmit.
for (i = 0; i < byteCount; ++i)
{
// Wait for transmitter to be ready. (This is causing the entire thing to crash)
while((SPSR & (1 << SPIF)) == 0);
// Transmit.
if (txLen > 0)
{
// Send data from the transmit buffer.
SPDR = (*p_txBuf++);
--txLen;
}
else
{
// No more Tx data to send, just send something to keep clock active.
SPDR = 0x00U;
}
// Wait for transfer to finish.
while((SPSR & (1 << SPIF)) == 0);
// Send dummy data to slave, so we can read something from it.
SPDR = 0x00U;
// Wait for transfer to finish.
while((SPSR & (1 << SPIF)) == 0);
// Read or throw away data from the slave as required.
if (rxLen > 0)
{
*p_rxBuf++ = SPDR;
--rxLen;
}
else
{
// Clear the registers
volatile uint8_t reg_clear = 0U;
reg_clear = SPDR;
(void)reg_clear;
}
}
}
I don't have enough information to say for sure, but my assumption is that your SPI connection is not set up correctly.
In particular, I guess you forgot to set /SS as output, same as this problem or this.
In the datasheet it says:
Master Mode When the SPI is configured as a master (MSTR in SPCR is
set), the user can determine the direction of the SS pin.
If SS is configured as an output, the pin is a general output pin
which does not affect the SPI system. Typically, the pin will be
driving the SS pin of the SPI slave.
If SS is configured as an input, it must be held high to ensure Master
SPI operation. If the SS pin is driven low by peripheral circuitry
when the SPI is configured as a master with the SS pin defined as an
input, the SPI system interprets this as another master selecting the
SPI as a slave and starting to send data to it. To avoid bus
contention, the SPI system takes the following actions:
The MSTR bit in SPCR is cleared and the SPI system becomes a slave. As a result of the SPI becoming a slave, the MOSI and SCK pins become
inputs.
The SPIF flag in SPSR is set, and if the SPI interrupt is enabled, and the I-bit in SREG is set, the interrupt routine will be executed.
Thus, when interrupt-driven SPI transmission is used in master mode,
and there exists a possibility that SS is driven low, the interrupt
should always check that the MSTR bit is still set. If the MSTR bit
has been cleared by a slave select, it must be set by the user to
re-enable SPI master mode.
So, you just need to configure the /SS pin as output and set to high in your init code, this should solve your problem:
DDRB |= (1 << PB0); // Set /SS (PB0) as output
PORTB |= (1 << PB0); // Set /SS (PB0) high

Why HM-10 doesn't send an OK if i send AT from an MSP430 Launchpad?

I'm trying to set up an UART communication with a HM-10 chip on a Texas Instruments MSP430 Launchpad, but I ran into a very elementary problem.
What I want to achieve is to send an "AT" through UART to HM-10, and receive an answer for that. By the way this is a code I found here and I slightly modified for my purposes.
#include "msp430g2553.h"
const char string[] = { "AT" };
unsigned int i;
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop the Watch dog
//------------------- Configure the Clocks -------------------//
if (CALBC1_1MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set range
DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation
//---------------- Configuring the LED's ----------------------//
P1DIR |= BIT0 + BIT6; // P1.0 and P1.6 output
P1OUT &= ~BIT0 + BIT6; // P1.0 and P1.6 = 0
//--------- Setting the UART function for P1.1 & P1.2 --------//
P1SEL |= BIT1 + BIT2; // P1.1 UCA0RXD input
P1SEL2 |= BIT1 + BIT2; // P1.2 UCA0TXD output
//------------ Configuring the UART(USCI_A0) ----------------//
UCA0CTL1 |= UCSSEL_2 + UCSWRST; // USCI Clock = SMCLK,USCI_A0 disabled
UCA0BR0 = 104; // 104 From datasheet table-
UCA0BR1 = 0; // -selects baudrate =9600,clk = SMCLK
UCA0MCTL = UCBRS_1; // Modulation value = 1 from datasheet
//UCA0STAT |= UCLISTEN; // loop back mode enabled
UCA0CTL1 &= ~UCSWRST; // Clear UCSWRST to enable USCI_A0
//---------------- Enabling the interrupts ------------------//
IE2 |= UCA0TXIE; // Enable the Transmit interrupt
IE2 |= UCA0RXIE; // Enable the Receive interrupt
_BIS_SR(GIE); // Enable the global interrupt
i = 0;
UCA0TXBUF = string[i]; // Transmit a byte
_BIS_SR(LPM0_bits + GIE); // Going to LPM0
}
//-----------------------------------------------------------------------//
// Transmit and Receive interrupts //
//-----------------------------------------------------------------------//
#pragma vector = USCIAB0TX_VECTOR
__interrupt void TransmitInterrupt(void)
{
P1OUT ^= BIT0;//light up P1.0 Led on Tx
if (i == sizeof string - 1)
{
UC0IE &= ~UCA0TXIE;
}
UCA0TXBUF = string[i++];
}
#pragma vector = USCIAB0RX_VECTOR
__interrupt void ReceiveInterrupt(void)
{
// light up P1.6 LED on RX
if (UCA0RXBUF == 'O')
{
P1OUT ^= BIT6;
}
IFG2 &= ~UCA0RXIFG; // Clear RX flag
}
According to the datasheet I should receive an OK answer for this command.
If there was an 'O' in the RX buffer, I would expect the LED to light up on my board, but that doesn't happen.
Using Code Composer, I also verified with adding a breakpoint to the RX interrupt that there is indeed no RX answer.
I believe this is entirely a software question, that's why I put it here. I'm using the correct rotation of jumpers(http://xanthium.in/Serial-Communication-MSP430-UART-USCI_A) and RX is wired to TX and vica versa.
I would appreciate if you could point out if I was doing anything conceptionally wrong or if I just made a mistake. Thank you!
I see a problem in the interrupt routine TransmitInterrupt(): you should use UCA0TXBUF = string[++i]; because using "i++" you transmit two times the letter "A". The test about sizeof(string) should also be retouched.
Then, I would not trust too much the datasheet. I think that, despite what the datasheet says, every command sent to the modem must be terminated by CR (\r), otherwise how could the modem discern an "AT" from an "AT+RESET"? I am not really sure but the datasheet doesn't seem a high quality one. Anyway, it's a quick test (to add a \r to the end of the string).
Finally, the CTS and RTS signals can play a role too. Some modem wants RTS asserted, other modems don't care, and terminology sometimes is confusing: when datasheet says RTS, does it mean RTS of the modem or RTS of the host? I hope this helps, you should do a few scientific tries.
I think for everyone who is working with HM-10 devices in the future I want to answer this question, because it has I think its own sort of mini-literature, which was first frustrating, but then I kind of liked the challenges it posed to me.
Some of the problems are hardware related, so this post might need to be moved to an embedded engineering section. (Great consequence - you cannot be 100% sure before checking it with a scope)
Know your hardware - HM-10 has tons of versions, and it turned our one needed an extra potential divider because it has a 3.3V logic level high instead of 5V. This website is a fantastic place to start. Though, ours turned out to be an MLT-BT05 which is a clone of a clone. It doesn't have iBeacon capability on its firmware, so if you don't want to power cycling, then you should probably avoid this one.
About the coding bit the most important thing is to check with \n, \r and \n\r, as linuxfan briefly mentioned its importance above, because some of the devices need it. The best place to start is AT and if it works, then use AT+HELP and find the version, usually AT+VERSION command so you can identify with 100% certainty which chip you have.
Currenetly it is prototyped on an Arduino, but I will include working code as soon as its finished on MSP430.
The Arduino code:
#include <SoftwareSerial.h>
SoftwareSerial bluetooth(9, 10); // RX, TX
char commandbuffer[50];
int j = 0;
void setup()
{
memset(commandbuffer, 0, sizeof(commandbuffer));
analogWrite(12, 255);
analogWrite(11, 0);
// Start the hardware serial port
Serial.begin(19200);
bluetooth.begin(9600);
// un REM this to set up a Master and connect to a Slave
Serial.println("BLE CC41A Bluetooth");
Serial.println("----------------------------------");
Serial.println("");
Serial.println("Trying to connect to Slave Bluetooth");
delay(1000);
bluetooth.println("AT"); // just a check
delay(2000);
bluetooth.println("AT+NAMEHIST");
delay(2000);
bluetooth.println("AT+ROLE0");
delay(2000);
bluetooth.println("AT+INQ"); // look for nearby Slave
delay(5000);
bluetooth.println("AT+CONN1"); // connect to it */
}
void loop()
{
bluetooth.listen();
// while there is data coming in, read it
// and send to the hardware serial port:
while (bluetooth.available() > 0) {
char inByte = bluetooth.read();
Serial.write(inByte);
}
// Read user input if available.
if (Serial.available()) {
delay(10); // The DELAY!
char temp = Serial.read();
if (temp == '\n')
{
bluetooth.println(commandbuffer);
Serial.println(commandbuffer);
memset(commandbuffer, 0, sizeof(commandbuffer));
j = 0; // Reset
}
else
{
commandbuffer[j++] = temp;
}
delay(500);
}

No interrupts being triggered in UART Receive on PIC18F2680

I have been working with this code for days and cannot figure out why my interrupts are not being triggered. I know data is coming through successfully because I used a probe on a logic analyzer, also my baud rate is correct as I can transmit with UART successfully.
At this point I'm lost, I've read the datasheet over and over and can't figure out my problem. I will try to include only the relative code but enough that you can see how things work in my project.
Please let me know if you see issues with this code.
Thank you!
Code snippets from main.c:
// USART RX interrupt priority
IPR1bits.RCIP = 0;
IPR1bits.TXIP = 0;
// configure the hardware USART device
OpenUSART(USART_TX_INT_OFF & USART_RX_INT_ON & USART_ASYNCH_MODE & USART_EIGHT_BIT &
USART_CONT_RX & USART_BRGH_LOW, 14);
Code snippets from interrupts.c
//----------------------------------------------------------------------------
// Low priority interrupt routine
// this parcels out interrupts to individual handlers
#pragma code
#pragma interruptlow InterruptHandlerLow
// This works the same way as the "High" interrupt handler
void InterruptHandlerLow() {
// check to see if we have an interrupt on USART RX
if (PIR1bits.RCIF) {
PIR1bits.RCIF = 0; //clear interrupt flag
uart_recv_int_handler();
}
// check to see if we have an interrupt on USART TX
if (PIR1bits.TXIF && PIE1bits.TXIE) {
// cannot clear TXIF, this is unique to USART TX
// so just call the handler
uart_tx_int_handler();
}
}
UART RX Interrupt Handler snippet:
void uart_recv_int_handler() {
int msgLen;
//if (DataRdyUSART()) {
uc_ptr->buffer[uc_ptr->buflen] = RCREG;
//uc_ptr->buffer[uc_ptr->buflen] = ReadUSART();
uc_ptr->buflen++;
}
}
Did you
- Set trisC6/7 correctly?
- if you have a part with analog inputs multiplexed on those pins, did you disable them?
- Is your BRG value validated for this part and these oscillator settings?
See also
http://www.piclist.com/techref/microchip/rs232.htm
I migrated to dspic, but I used to do the serial receive under interrupt. This I had in the interrupt (serialin1 is a power of two circular buffer, lastserialin1 the pointer into it, and ser1bufinmask is size of buffer-1)
if (PIR1bits.RCIF == 1) /* check if RC interrupt (receive USART) must be serviced
{
while (PIR1bits.RCIF == 1) /* flag becomes zero if buffer/fifo is empty */
{
lastserialin1=(lastserialin1+1)&ser1bufinmask;
serialin1[lastserialin1]=RCREG;
}
}
To initialize the uart I had:
// Configure USART
TXSTA = 0x20; // transmit enable
RCSTA = 0x90; // spen en cren
RCONbits.IPEN = 1; /* Interrupt Priority Enable Bit. Enable priority levels on interrupts */
INTCONbits.GIE = 1; /* Set GIE. Enables all high priority unmasked interrupts */
INTCONbits.GIEL = 1; /* Set GIEL. Enables all low priority unmasked interrupts */
TRISCbits.TRISC6 = 0; // page 237
TRISCbits.TRISC7 = 1; // page 237
Open1USART (
USART_TX_INT_OFF
&
USART_RX_INT_ON &
USART_ASYNCH_MODE &
USART_EIGHT_BIT & // 8-bit transmit/receive
USART_CONT_RX & // Continuous reception
// USART_BRGH_HIGH, 155); // High baud rate, 155 eq 19k2
USART_BRGH_HIGH, brgval); // High baud rate, 25 eq 115k2
IPR1bits.RCIP = 0;
PIR1bits.RCIF = 0;
with brgval calculated using
#define GetInstructionClock() (GetSystemClock()/4)
#define GetPeripheralClock() GetInstructionClock()
// See if we can use the high baud rate setting
#if ((GetPeripheralClock()+2*BAUD_RATE)/BAUD_RATE/4 - 1) <= 255
#define BRGVAL ((GetPeripheralClock()+2*BAUD_RATE)/BAUD_RATE/4 - 1)
#define BRGHVAL (1)
#else // Use the low baud rate setting
#define BRGVAL ((GetPeripheralClock()+8*BAUD_RATE)/BAUD_RATE/16 - 1)
#define BRGHVAL (0)
#endif

PIC Capture mode not triggering interrupt

I'm trying to use the capture module on a PIC 16LF1827, but the ISR is never entered. I started with a basic falling-edge interrupt (worked), then added in the timer 1 configuration (still working), then disabled the IOC interrupt and configured/enabled the relevant CCP interrupt (ISR is never entered). The code is below: the commented section is the original basic IOC setup.
I've verified with the MPLab debugger that the ISR is not entered, and confirmed this by hooking it up to a logic analyzer and watching RB1.
#include "htc.h"
//config1
//internal osc, no wdt, use power-up timer, enable reset
// no code protection, brown-out-reset enabled, clkout is gpio,
// internal-external switchover off, failsafe clock monitor off
__CONFIG(FOSC_INTOSC & WDTE_OFF & PWRTE_ON
& MCLRE_ON & CP_OFF & CPD_OFF & BOREN_ON
& CLKOUTEN_OFF & IESO_OFF & FCMEN_OFF);
//config2 (following MPLab's complaints when running debugger)
//low-voltage programming off, debug on, brown-out reset at 2.7 v
// stack over/under flow triggers reset, no 4x pll,
// no flash write protection
__CONFIG(LVP_OFF & DEBUG_ON & BORV_27
& STVREN_ON & PLLEN_OFF & WRT_OFF);
void interrupt isr(void){
//bounce pin 1
LATB ^= 0b10;
LATB ^= 0b10;
if(IOCIF && IOCBF0){
IOCBF0 = 0;
IOCIF = 0;
}
if (CCP1IF){
CCP1IF = 0;
}
}
void main(void){
//configure internal oscillator:
//PLL = 0, source = from config 1, frequency = 4 mhz
//0b0: SPLLEN_OFF
OSCCONbits.SPLLEN = 0b0;
//0b00: use config word 1
OSCCONbits.SCS = 0b00;
//0b1101: 4 mhz frequency
OSCCONbits.IRCF = 0b1101;
//configure peripherals
//PORT A: LEDs (output), digital
TRISA = 0x00;
ANSELA = 0;
//PORT B: digital, 0 = input, 1 = output, rest don't care
TRISB = 0b11111101;
ANSELB = 0;
//configure timer 1 (not needed for basic IOC)
//source = instruction clock, prescale = 1:1, disable LP osc, do synchronize (DC)
//0b00: instruction clock
T1CONbits.TMR1CS = 0b00;
//0b00: 1:1
T1CONbits.T1CKPS = 0b00;
//0b0: lp osc off
T1OSCEN = 0b0;
//0b0: synch (ignored)
nT1SYNC = 0b0;
//interrupts
/*
//IOC enabled on falling edge for port B 0
IOCBN0 = 0b00000001;
IOCIE = 1;
*/
//Capture on falling edge for port B 0
//notes in 23.1 of DS: disable interrupt, set operating mode, clear flag, enable interrupt
CCP1IE = 0b0;
//0b100: every falling edge
CCP1CONbits.CCP1M = 0b100;
CCP1IF = 0b0;
CCP1IE = 0b1;
//enable peripheral interrupts, global interrupts
PEIE = 1;
GIE = 1;
//start timer 1
TMR1ON = 1;
while(1){
//Toggle led 0
LATA ^= 0b1;
}
}
I'm using the HI-TECH C compiler (lite), running in MPLab.
Any suggestions would be greatly appreciated. My apologies if I butcher terminology, this is my first project on a PIC.
Your setting for TRISB1 is as an output. According to the datasheet, the capture pin needs to be configured as an input. For the GPIO pins, setting the TRIS bit a 0 is an output, 1 is for an input.
EDIT: Forgive the initial stupid answer as I didn't realize you were using PORTB1 as a GPIO indicator for your scope.
So initially you used PORTB0 as your capture pin correct (using IOC)? The capture module uses a different GPIO port for its input (PORTB3 for CCP1). Did you move the connection to PORTB3 for your capture source?
EDIT: After some more looking through the PIC datasheet I noticed that CCP1's GPIO pin can be moved from PORTB3 to PORTB0 but I don't see any reference to how you set the APFCON0.CCP1SEL bit. That would be something else to check.