Hi,
I'am currently programming with my freedom kl46z board and I spend a few day trying to use the LCD.
First I find on the internet a library that allow to use the LCD in very simple mode on this website :
https://eewiki.net/display/microcontroller/Using+the+Segment+LCD+Controller+on+the+Kinetis+KL46
This code work when I implement it on an example like hello world. But when I do an empty project the code don't work at all. I suspect I forget to initialize something but I can't figure out what.
In my project I'am able to use the Led and switch but the LCD don't want to work.
I hope I have been clear if not please ask me question.
Thanks a lot for your answer. It works now !
OK, if your problem is solved, please help us to mark the correct answer to close this case.
Thank you!
Have a great day,
Kerry
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Florian,
About the SLCD code for FRDM-KL46, you also can refer to the sample code for FRDM-KL46, please download the code from this link:
http://cache.nxp.com/files/32bit/software/KL46_SC.exe
After you install it, you can find the SLCD code in folder:kinetis_kl46_sc_rev2\klxx-sc-baremetal\build\iar\sLCD_freedom
This code is very simple to understand and transplant.
If you still meet problem, just contact me!
Have a great day,
Kerry
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi
See
http://www.utasker.com/kinetis/FRDM-KL46Z.html
http://www.utasker.com/kinetis/TWR-KL46Z48M.html
and
http://www.utasker.com/docs/uTasker/uTasker_SLCD.pdf
and
https://www.youtube.com/watch?v=nm2DmZv1rj8
With these nothing can go wrong. Possibly when you mix examples you have indeed skipped some initialiation but also it may be that there are port conflicts.
Regards
Mark
Kinetis for professionals: http://www.utasker.com/kinetis.html
As reference - this is initialisation code for the SLCD on the FRDM-KL46
// Use MCGIRCLK (fast IRC) as SLCD source
//
#define CONFIGURE_SLCD() MCG_C1 &= ~(MCG_C1_IREFS); MCG_C1 |= (MCG_C1_IRCLKEN | MCG_C1_IREFSTEN); \
POWER_UP(5, SIM_SCGC5_SLCD); \
LCD_GCR = (LCD_GCR_RVEN | (0x08000000 & LCD_GCR_RVTRIM_MASK) | LCD_GCR_CPSEL | LCD_GCR_LADJ_MASK | LCD_GCR_VSUPPLY | LCD_GCR_SOURCE | LCD_GCR_LCLK_1 | LCD_GCR_DUTY_4BP); \
LCD_AR = (LCD_AR_BRATE_MASK & 3); \
LCD_BPENL = (SLCD_PIN_19 | SLCD_PIN_18); \
LCD_BPENH = (SLCD_PIN_H_52 | SLCD_PIN_H_40); \
LCD_PENL = ((SLCD_PIN_17 | SLCD_PIN_11 | SLCD_PIN_10 | SLCD_PIN_8 | SLCD_PIN_7) | (SLCD_PIN_19 | SLCD_PIN_18)); \
LCD_PENH = ((SLCD_PIN_H_53 | SLCD_PIN_H_38 | SLCD_PIN_H_37) | (SLCD_PIN_H_52 | SLCD_PIN_H_40)); \
fnClearSLCD(); \
WRITE_SLCD(43TO40, 0x00000001); \
WRITE_SLCD(55TO52, 0x00000002); \
WRITE_SLCD(19TO16, 0x04080000); \
LCD_GCR = (LCD_GCR_LCDEN | LCD_GCR_RVEN | (0x08000000 & LCD_GCR_RVTRIM_MASK) | LCD_GCR_CPSEL | LCD_GCR_LADJ_MASK | LCD_GCR_VSUPPLY | LCD_GCR_SOURCE | LCD_GCR_LCLK_1 | LCD_GCR_DUTY_4BP)
// The SLCD controller may retain segment settings across resets so this initialisation routine is used to ensure all are cleared when starting
//
extern void fnClearSLCD(void)
{
unsigned long *ptrSegments = LCD_WF3TO0_ADDR;
int i = 0;
while (i++ < SEGMENT_REGISTER_COUNT) {
*ptrSegments++ = 0;
}
}
And the following is a clock display updated every second by a 1s interrupt (eg. from RTC)
static void _rtc_second_interrupt(void) // seconds interrupt call-back handler
{
RTC_SETUP rtc_setup;
rtc_setup.command = RTC_GET_TIME;
fnConfigureRTC(&rtc_setup); // get the present time
if (IS_POWERED_UP(5, SIM_SCGC5_SLCD)) { // display time as long as the SLCD has been enabled
fnTimeDisplay(rtc_setup.ucHours, rtc_setup.ucMinutes, rtc_setup.ucSeconds);
}
}
with the complete SLCD code below to allow digits to be simply displayed.
// Register LCD_WF19TO16 and LCD_WF39TO36 (tens of hours)
//
#define SEVEN_SEGMENT_0_TOP 0x00000800 // 17-8
#define SEVEN_SEGMENT_0_MID 0x00000400 // 37-4
#define SEVEN_SEGMENT_0_BOT 0x00000100 // 37-1
#define SEVEN_SEGMENT_0_T_L 0x00000800 // 37-8
#define SEVEN_SEGMENT_0_B_L 0x00000200 // 37-2
#define SEVEN_SEGMENT_0_T_R 0x00000400 // 17-4
#define SEVEN_SEGMENT_0_B_R 0x00000200 // 17-2
#define SEVEN_SEGMENT_0_17 (SEVEN_SEGMENT_0_TOP | SEVEN_SEGMENT_0_T_R | SEVEN_SEGMENT_0_B_R)
#define SEVEN_SEGMENT_0_37 (SEVEN_SEGMENT_0_MID | SEVEN_SEGMENT_0_BOT | SEVEN_SEGMENT_0_T_L | SEVEN_SEGMENT_0_B_L)
#define SEVEN_SEGMENT_0_0 (SEVEN_SEGMENT_0_17 | SEVEN_SEGMENT_0_37)
#define SEVEN_SEGMENT_0_1 (SEVEN_SEGMENT_0_T_R | SEVEN_SEGMENT_0_B_R)
#define SEVEN_SEGMENT_0_2 ((SEVEN_SEGMENT_0_TOP | SEVEN_SEGMENT_0_T_R | SEVEN_SEGMENT_0_MID | SEVEN_SEGMENT_0_B_L | SEVEN_SEGMENT_0_BOT) & SEVEN_SEGMENT_0_17)
// Register LCD_WF11TO8 and LCD_WF7TO4 (hours)
//
#define SEVEN_SEGMENT_1_TOP 0x00000008 // 8-8
#define SEVEN_SEGMENT_1_MID 0x04000000 // 7-4
#define SEVEN_SEGMENT_1_BOT 0x01000000 // 7-1
#define SEVEN_SEGMENT_1_T_L 0x08000000 // 7-8
#define SEVEN_SEGMENT_1_B_L 0x02000000 // 7-2
#define SEVEN_SEGMENT_1_T_R 0x00000004 // 8-4
#define SEVEN_SEGMENT_1_B_R 0x00000002 // 8-2
#define SEVEN_SEGMENT_1__7 (SEVEN_SEGMENT_1_MID | SEVEN_SEGMENT_1_BOT | SEVEN_SEGMENT_1_T_L | SEVEN_SEGMENT_1_B_L)
#define SEVEN_SEGMENT_1__8 (SEVEN_SEGMENT_1_TOP | SEVEN_SEGMENT_1_T_R | SEVEN_SEGMENT_1_B_R)
#define SEVEN_SEGMENT_1 (SEVEN_SEGMENT_1__7 | SEVEN_SEGMENT_1__8)
#define SEVEN_SEGMENT_1_0 (SEVEN_SEGMENT_1 & ~(SEVEN_SEGMENT_1_MID))
#define SEVEN_SEGMENT_1_1 (SEVEN_SEGMENT_1_T_R | SEVEN_SEGMENT_1_B_R)
#define SEVEN_SEGMENT_1_2 (SEVEN_SEGMENT_1 & ~(SEVEN_SEGMENT_1_T_L | SEVEN_SEGMENT_1_B_R))
#define SEVEN_SEGMENT_1_3 (SEVEN_SEGMENT_1 & ~(SEVEN_SEGMENT_1_T_L | SEVEN_SEGMENT_1_B_L))
#define SEVEN_SEGMENT_1_4 (SEVEN_SEGMENT_1 & ~(SEVEN_SEGMENT_1_TOP | SEVEN_SEGMENT_1_B_L | SEVEN_SEGMENT_1_BOT))
#define SEVEN_SEGMENT_1_5 (SEVEN_SEGMENT_1 & ~(SEVEN_SEGMENT_1_B_L | SEVEN_SEGMENT_1_T_R))
#define SEVEN_SEGMENT_1_6 (SEVEN_SEGMENT_1 & ~(SEVEN_SEGMENT_1_T_R))
#define SEVEN_SEGMENT_1_7 (SEVEN_SEGMENT_1_T_R | SEVEN_SEGMENT_1_B_R | SEVEN_SEGMENT_1_TOP)
#define SEVEN_SEGMENT_1_8 SEVEN_SEGMENT_1
#define SEVEN_SEGMENT_1_9 (SEVEN_SEGMENT_1 & ~(SEVEN_SEGMENT_1_B_L))
// Registers LCD_WF39TO36 and LCD_WF55TO52 (tens of minutes)
//
#define SEVEN_SEGMENT_2_TOP 0x00080000 // 38-8
#define SEVEN_SEGMENT_2_MID 0x00000400 // 53-4
#define SEVEN_SEGMENT_2_BOT 0x00000100 // 53-1
#define SEVEN_SEGMENT_2_T_L 0x00000800 // 53-8
#define SEVEN_SEGMENT_2_B_L 0x00000200 // 53-2
#define SEVEN_SEGMENT_2_T_R 0x00040000 // 38-4
#define SEVEN_SEGMENT_2_B_R 0x00020000 // 38-2
#define SEVEN_SEGMENT_2_38 (SEVEN_SEGMENT_2_TOP | SEVEN_SEGMENT_2_T_R | SEVEN_SEGMENT_2_B_R)
#define SEVEN_SEGMENT_2_53 (SEVEN_SEGMENT_2_MID | SEVEN_SEGMENT_2_BOT | SEVEN_SEGMENT_2_T_L | SEVEN_SEGMENT_2_B_L)
#define SEVEN_SEGMENT_2 (SEVEN_SEGMENT_2_38 | SEVEN_SEGMENT_2_53)
#define SEVEN_SEGMENT_2_0 (SEVEN_SEGMENT_2 & ~(SEVEN_SEGMENT_2_MID))
#define SEVEN_SEGMENT_2_1 (SEVEN_SEGMENT_2_T_R | SEVEN_SEGMENT_2_B_R)
#define SEVEN_SEGMENT_2_2 (SEVEN_SEGMENT_2 & ~(SEVEN_SEGMENT_2_T_L | SEVEN_SEGMENT_2_B_R))
#define SEVEN_SEGMENT_2_3 (SEVEN_SEGMENT_2 & ~(SEVEN_SEGMENT_2_T_L | SEVEN_SEGMENT_2_B_L))
#define SEVEN_SEGMENT_2_4 (SEVEN_SEGMENT_2 & ~(SEVEN_SEGMENT_2_TOP | SEVEN_SEGMENT_2_B_L | SEVEN_SEGMENT_2_BOT))
#define SEVEN_SEGMENT_2_5 (SEVEN_SEGMENT_2 & ~(SEVEN_SEGMENT_2_B_L | SEVEN_SEGMENT_2_T_R))
#define SEVEN_SEGMENT_2_6 (SEVEN_SEGMENT_2 & ~(SEVEN_SEGMENT_2_T_R))
#define SEVEN_SEGMENT_2_7 (SEVEN_SEGMENT_2_T_R | SEVEN_SEGMENT_2_B_R | SEVEN_SEGMENT_2_TOP)
#define SEVEN_SEGMENT_2_8 (SEVEN_SEGMENT_2)
#define SEVEN_SEGMENT_2_9 (SEVEN_SEGMENT_2 & ~(SEVEN_SEGMENT_2_B_L))
// Register LCD_WF11TO8 (minutes)
//
#define SEVEN_SEGMENT_3_TOP 0x08000000 // 11-8
#define SEVEN_SEGMENT_3_MID 0x00040000 // 10-4
#define SEVEN_SEGMENT_3_BOT 0x00010000 // 10-1
#define SEVEN_SEGMENT_3_T_L 0x00080000 // 10-8
#define SEVEN_SEGMENT_3_B_L 0x00020000 // 10-2
#define SEVEN_SEGMENT_3_T_R 0x04000000 // 11-4
#define SEVEN_SEGMENT_3_B_R 0x02000000 // 11-2
#define SEGMENT_COLON 0x01
#define SEVEN_SEGMENT_3 (SEVEN_SEGMENT_3_TOP | SEVEN_SEGMENT_3_MID | SEVEN_SEGMENT_3_BOT | SEVEN_SEGMENT_3_T_L | SEVEN_SEGMENT_3_B_L | SEVEN_SEGMENT_3_T_R | SEVEN_SEGMENT_3_B_R)
#define SEVEN_SEGMENT_3_0 (SEVEN_SEGMENT_3 & ~(SEVEN_SEGMENT_3_MID))
#define SEVEN_SEGMENT_3_1 (SEVEN_SEGMENT_3_T_R | SEVEN_SEGMENT_3_B_R)
#define SEVEN_SEGMENT_3_2 (SEVEN_SEGMENT_3 & ~(SEVEN_SEGMENT_3_T_L | SEVEN_SEGMENT_3_B_R))
#define SEVEN_SEGMENT_3_3 (SEVEN_SEGMENT_3 & ~(SEVEN_SEGMENT_3_T_L | SEVEN_SEGMENT_3_B_L))
#define SEVEN_SEGMENT_3_4 (SEVEN_SEGMENT_3 & ~(SEVEN_SEGMENT_3_TOP | SEVEN_SEGMENT_3_B_L | SEVEN_SEGMENT_3_BOT))
#define SEVEN_SEGMENT_3_5 (SEVEN_SEGMENT_3 & ~(SEVEN_SEGMENT_3_B_L | SEVEN_SEGMENT_3_T_R))
#define SEVEN_SEGMENT_3_6 (SEVEN_SEGMENT_3 & ~(SEVEN_SEGMENT_3_T_R))
#define SEVEN_SEGMENT_3_7 (SEVEN_SEGMENT_3_T_R | SEVEN_SEGMENT_3_B_R | SEVEN_SEGMENT_3_TOP)
#define SEVEN_SEGMENT_3_8 SEVEN_SEGMENT_3
#define SEVEN_SEGMENT_3_9 (SEVEN_SEGMENT_3 & ~(SEVEN_SEGMENT_3_B_L))
static const unsigned long ulSegment1[] = { // hours 0..9
SEVEN_SEGMENT_1_0,
SEVEN_SEGMENT_1_1,
SEVEN_SEGMENT_1_2,
SEVEN_SEGMENT_1_3,
SEVEN_SEGMENT_1_4,
SEVEN_SEGMENT_1_5,
SEVEN_SEGMENT_1_6,
SEVEN_SEGMENT_1_7,
SEVEN_SEGMENT_1_8,
SEVEN_SEGMENT_1_9,
};
static const unsigned long ulSegment2[] = { // tens of minutes 0..5
SEVEN_SEGMENT_2_0,
SEVEN_SEGMENT_2_1,
SEVEN_SEGMENT_2_2,
SEVEN_SEGMENT_2_3,
SEVEN_SEGMENT_2_4,
SEVEN_SEGMENT_2_5,
};
static const unsigned long ulSegment3[] = { // minutes 0..9
(SEVEN_SEGMENT_3_0 >> 0),
(SEVEN_SEGMENT_3_1 >> 0),
(SEVEN_SEGMENT_3_2 >> 0),
(SEVEN_SEGMENT_3_3 >> 0),
(SEVEN_SEGMENT_3_4 >> 0),
(SEVEN_SEGMENT_3_5 >> 0),
(SEVEN_SEGMENT_3_6 >> 0),
(SEVEN_SEGMENT_3_7 >> 0),
(SEVEN_SEGMENT_3_8 >> 0),
(SEVEN_SEGMENT_3_9 >> 0),
};
static void fnTimeDisplay(unsigned char ucHours, unsigned char ucMinutes, unsigned char ucSeconds)
{
unsigned long ulRegister;
ulRegister = LCD_WF19TO16;
ulRegister &= ~(SEVEN_SEGMENT_0_17);
switch (ucHours/10) {
case 1:
ulRegister |= (SEVEN_SEGMENT_0_B_R | SEVEN_SEGMENT_0_T_R); // set the tens of hours ('1')
break;
case 2:
ulRegister |= (SEVEN_SEGMENT_0_TOP | SEVEN_SEGMENT_0_T_R); // set the tens of hours ('2')
break;
}
WRITE_SLCD(19TO16, ulRegister); // tens of hours (part 1)
ulRegister = LCD_WF39TO36;
ulRegister &= ~(SEVEN_SEGMENT_0_37);
switch (ucHours/10) {
case 2:
ulRegister |= (SEVEN_SEGMENT_0_MID | SEVEN_SEGMENT_0_B_L | SEVEN_SEGMENT_0_BOT); // set the tens of hours ('2')
break;
}
WRITE_SLCD(39TO36, ulRegister); // tens of hours (part 2)
ucHours -= ((ucHours/10) * 10);
ulRegister = LCD_WF7TO4;
ulRegister &= ~(SEVEN_SEGMENT_1__7);
ulRegister |= (ulSegment1[ucHours] & SEVEN_SEGMENT_1__7); // set the hours
WRITE_SLCD(7TO4, ulRegister); // hours (part 1)
ulRegister = LCD_WF11TO8;
ulRegister &= ~(SEVEN_SEGMENT_1__8);
ulRegister |= (ulSegment1[ucHours] & SEVEN_SEGMENT_1__8); // set the hours
WRITE_SLCD(11TO8, ulRegister); // hours (part 2)
ulRegister = LCD_WF39TO36;
ulRegister &= ~(SEVEN_SEGMENT_2_38);
ulRegister |= (ulSegment2[ucMinutes/10] & SEVEN_SEGMENT_2_38); // set the tens of minutes
WRITE_SLCD(39TO36, ulRegister); // tens of minutes (part 1)
ulRegister = LCD_WF55TO52;
ulRegister &= ~(SEVEN_SEGMENT_2_53);
ulRegister |= (ulSegment2[ucMinutes/10] & SEVEN_SEGMENT_2_53); // set the tens of minutes
WRITE_SLCD(55TO52, ulRegister); // tens of minutes (part 2)
ulRegister = LCD_WF11TO8;
ulRegister &= ~(SEVEN_SEGMENT_3);
ucMinutes -= ((ucMinutes/10) * 10);
ulRegister |= ulSegment3[ucMinutes];
WRITE_SLCD(11TO8, ulRegister); // minutes
TOGGLE_SLCD(11, SEGMENT_COLON); // toggle ':'
}
And finally, what it looks like when run in the uTasker simulator:
Regards
Mark