This is a fairly basic question but I am fairly new to this and I have not been able to find any solution. I am trying to initilize an interrupt routine when the Receive Data Register is full for the LPUART function. My debug tests have shown that when I transmit 0x55 into pinB2, there is a detection on the rising edge (LPUART0_STAT(RXEDGIF =1)), but it never fills up the buffer (LPUART0_STAT(RDRF=0)). My register set up is seen below, am I missing something for setting up the registers or is there something else?
/////////////////////////////////////LPUART Setup///////////////////////////////////////////////////////
//setting System Integration Module//
SIM_BWR_SOPT5_LPUART0RXSRC(SIM_BASE_PTR, 0); //select LPUART_RX pin to receive data
SIM_BWR_SCGC5_LPUART0(SIM_BASE_PTR, 1);//enabling UART clock
SIM_BWR_SCGC5_PORTB(SIM_BASE_PTR, 1);//enables clock gate of Port B
///////Port Set-up///////
PORT_BWR_PCR_MUX(PORTB, 2, 0b010); //Set the Alt2 muxing on Port B, pin 2 for UART0_RX
PORT_BWR_PCR_IRQC(PORTB, 2, 0b1011);//Interrupt configuration to happen on either edge
//Setting the BAUD register//
//To achieve a baud rate of 300, we want SBR=2 [0000000000010] and OSR=4 [11111]
LPUART_BWR_BAUD_SBR(LPUART0,0b0000000010110); //Setting SBR =22
LPUART_BWR_BAUD_OSR(LPUART0, 0b00011); //OSR= x4
LPUART_BWR_BAUD_RXEDGIE(LPUART0, 1); //enabling hardware interrupts from STAT register
//setting CTRL register//
LPUART_BWR_CTRL_RIE(LPUART0, 1); //receiver data buffer full interrupt (1-enable 0-disable)
LPUART_BWR_CTRL_RE(LPUART0, 1);//enabling receiver mode
LPUART_BWR_CTRL_IDLECFG(LPUART0, 0b010);//configures 4 idle characters before an idle flag is set
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Would really appreciate it and sorry for the relative simplicity of this question. Let me know if you need any more information.
解決済! 解決策の投稿を見る。
Hi
Here are KL03 LPUART0 initialisation and rx interrupt handling snippets from the uTasker project as reference. You can get complete code from the uTasker open source project at the links below which also enables you to simulate the complete operation to avoid complications, and accelerate learning and developments.
This shows the 48MHz IRC48M clock being used as source and configuring for 115'200 Baud.
#define SPECIAL_LPUART_CLOCK (48000000)
KINETIS_LPUART_CONTROL lpuart_reg= uart_reg = (KINETIS_LPUART_CONTROL *)UART0_BLOCK; // select the register set for use by this channel
POWER_UP(5, SIM_SCGC5_LPUART0); // power up LPUART 0
MCG_MC |= MCG_MC_HIRCEN; // ensure that the IRC48M is operating, even when the processor is not in HIRC mode
SIM_SOPT2 = ((SIM_SOPT2 & ~(SIM_SOPT2_UART0SRC_MCGIRCLK)) | (SIM_SOPT2_UART0SRC_IRC48M | SIM_SOPT2_PLLFLLSEL_IRC48M)); // select the 48MHz IRC48MHz clock as source for the LPUART
lpuart_reg->LPUART_BAUD = (((SPECIAL_UART_CLOCK/8/115200) + 1)/2); // set 115200
lpuart_reg->LPUART_CTRL = 0; // 8 bit, no parity
_CONFIG_PERIPHERAL(B, 2, (PB_2_LPUART0_RX | UART_PULL_UPS)); // LPUART0_RX on PB2
_CONFIG_PERIPHERAL(B, 1, (PB_1_LPUART0_TX | UART_PULL_UPS)); // LPUART0_TX on PB1
fnEnterInterrupt(irq_LPUART0_ID, PRIORITY_LPUART0, _LPSCI0_Interrupt); // enter LPUART0 interrupt handler for rx and tx
lpuart_reg->LPUART_CTRL |= (LPUART_CTRL_RIE | LPUART_CTRL_RE | LPUART_CTRL_TE); // enable transmitter/receiver and rx interrupt
// LPUART 0 interrupt handler
//
static __interrupt void _LPSCI0_Interrupt(void)
{
unsigned long ulState = LPUART0_STAT; // status register on entry to the interrupt routine
if (((ulState & LPUART_STAT_RDRF) & LPUART0_CTRL) != 0) { // reception interrupt flag is set and the reception interrupt is enabled
fnSciRxByte((unsigned char)(LPUART0_DATA), LPUART0_CH_NUMBER); // receive data interrupt - read the byte
ulState = LPUART0_STAT; // update the status register
if ((ulState & LPUART_STAT_OR) != 0) { // if the overrun flag is set at this point it means that an overrun took place between reading the status register on entry to the interrupt and reading the data register
(void)LPUART0_DATA; // read the data register in order to clear the overrun flag and allow the receiver to continue operating
}
}
if (((ulState & LPUART_STAT_TDRE) & LPUART0_CTRL) != 0) { // transmit buffer is empty and the transmit interrupt is enabled
fnSciTxByte(LPUART0_CH_NUMBER); // transmit data empty interrupt - write next byte, if waiting
}
}
If you are not interested in optimal development efficiency and just in correcting your new code I believe that you have forgotten to enable clocks to the LPUART itself. See
MCG_MC |= MCG_MC_HIRCEN; // optional if the processor is already operating in HIRC mode
and
SIM_SOPT2 = ((SIM_SOPT2 & ~(SIM_SOPT2_UART0SRC_MCGIRCLK)) | (SIM_SOPT2_UART0SRC_IRC48M | SIM_SOPT2_PLLFLLSEL_IRC48M)); // without this the LPUART is in a frozen state - the edge interrupt will still operate since it is a special asynchronous interrupt but no actual LPUART functions will work yet.
Regards
Mark
http://www.utasker.com/kinetis/FRDM-KL03Z.html
http://www.utasker.com/kinetis.html
Hi Beau,
Would you please attached your project here, so that we can help you easier.
Don't know the 'LPUART ASYNCH Module Clock' that you selected, so I am not sure if the baudrate is well configured. But you can check the baudrate through send 0x55 and observe it by oscilloscope.
If you select 48MHz IRC48M. To achieve a baud rate of 300, you need set SBR=0x1388 and OSR=0x1F.
I recommand you test the lpuart example in SDK_2.2_FRDM-KL03Z. You can download it refer Generating a downloadable MCUXpresso SDK v.2 package.
Best Regards,
Robin
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Yeah it works as desired and I was using 0x55 for testing. To get the 300 baud rate I used the 48Mhz internal RC clock and used SBR=4848 (1001011110000) and the OSR=32 (11111). When I send the characters through it detects them correctly. I'm not too sure where you are getting the 1388 SBR value. Using that formula with OSR=32 would suggest a baud rate of around 1048.
Hi Beau
SBR = 0x1388 is correct for 300 Baud. This is 5000 and gives exactly 300.0 Baud from a 48MHz clock.
Your value of 4848 gives 309.4 Baud, which is adequate to operate (+3%) but is not absolutely correct.
Regards
Mark
Hi Mark,
Sorry, I am not quite seeing where the 5000 is coming from and how that gives a 300 baud rate. With the numbers I am using I am finding that my baud rate is IRC48M/(SBR*(OSR+1))=48Meg/(4848*(32+1))=300.03 baud. Is there an aspect that I am not understanding?
Regards,
Beau
Hi Beau
RC48M/(SBR*(OSR+1))=48Meg/(4848*(31+1))=309.41
RC48M/(SBR*(OSR+1))=48Meg/(5000*(31+1))=300.00
You were using the wrong value for OSR - is is the value in the register (0x1f = 31).
Regards
Mark
Oh I see now, that makes sense. The manual describes setting the OSR register to 11111 as being 32, so that is where my confusion was. I was wondering why there was a +1 in the baud calculation. Thanks a lot Mark and Robin.
Hi
Here are KL03 LPUART0 initialisation and rx interrupt handling snippets from the uTasker project as reference. You can get complete code from the uTasker open source project at the links below which also enables you to simulate the complete operation to avoid complications, and accelerate learning and developments.
This shows the 48MHz IRC48M clock being used as source and configuring for 115'200 Baud.
#define SPECIAL_LPUART_CLOCK (48000000)
KINETIS_LPUART_CONTROL lpuart_reg= uart_reg = (KINETIS_LPUART_CONTROL *)UART0_BLOCK; // select the register set for use by this channel
POWER_UP(5, SIM_SCGC5_LPUART0); // power up LPUART 0
MCG_MC |= MCG_MC_HIRCEN; // ensure that the IRC48M is operating, even when the processor is not in HIRC mode
SIM_SOPT2 = ((SIM_SOPT2 & ~(SIM_SOPT2_UART0SRC_MCGIRCLK)) | (SIM_SOPT2_UART0SRC_IRC48M | SIM_SOPT2_PLLFLLSEL_IRC48M)); // select the 48MHz IRC48MHz clock as source for the LPUART
lpuart_reg->LPUART_BAUD = (((SPECIAL_UART_CLOCK/8/115200) + 1)/2); // set 115200
lpuart_reg->LPUART_CTRL = 0; // 8 bit, no parity
_CONFIG_PERIPHERAL(B, 2, (PB_2_LPUART0_RX | UART_PULL_UPS)); // LPUART0_RX on PB2
_CONFIG_PERIPHERAL(B, 1, (PB_1_LPUART0_TX | UART_PULL_UPS)); // LPUART0_TX on PB1
fnEnterInterrupt(irq_LPUART0_ID, PRIORITY_LPUART0, _LPSCI0_Interrupt); // enter LPUART0 interrupt handler for rx and tx
lpuart_reg->LPUART_CTRL |= (LPUART_CTRL_RIE | LPUART_CTRL_RE | LPUART_CTRL_TE); // enable transmitter/receiver and rx interrupt
// LPUART 0 interrupt handler
//
static __interrupt void _LPSCI0_Interrupt(void)
{
unsigned long ulState = LPUART0_STAT; // status register on entry to the interrupt routine
if (((ulState & LPUART_STAT_RDRF) & LPUART0_CTRL) != 0) { // reception interrupt flag is set and the reception interrupt is enabled
fnSciRxByte((unsigned char)(LPUART0_DATA), LPUART0_CH_NUMBER); // receive data interrupt - read the byte
ulState = LPUART0_STAT; // update the status register
if ((ulState & LPUART_STAT_OR) != 0) { // if the overrun flag is set at this point it means that an overrun took place between reading the status register on entry to the interrupt and reading the data register
(void)LPUART0_DATA; // read the data register in order to clear the overrun flag and allow the receiver to continue operating
}
}
if (((ulState & LPUART_STAT_TDRE) & LPUART0_CTRL) != 0) { // transmit buffer is empty and the transmit interrupt is enabled
fnSciTxByte(LPUART0_CH_NUMBER); // transmit data empty interrupt - write next byte, if waiting
}
}
If you are not interested in optimal development efficiency and just in correcting your new code I believe that you have forgotten to enable clocks to the LPUART itself. See
MCG_MC |= MCG_MC_HIRCEN; // optional if the processor is already operating in HIRC mode
and
SIM_SOPT2 = ((SIM_SOPT2 & ~(SIM_SOPT2_UART0SRC_MCGIRCLK)) | (SIM_SOPT2_UART0SRC_IRC48M | SIM_SOPT2_PLLFLLSEL_IRC48M)); // without this the LPUART is in a frozen state - the edge interrupt will still operate since it is a special asynchronous interrupt but no actual LPUART functions will work yet.
Regards
Mark
http://www.utasker.com/kinetis/FRDM-KL03Z.html
http://www.utasker.com/kinetis.html
Thank you very much Mark, that was indeed my problem. At the moment I am just looking to fix my code but after some proof of concept I will probably be trying to optimize it.