📄 lcdinterface.c
字号:
TMR2CN = 0x00; // STOP Timer2; Clear TF2H and TF2L;
// disable low-byte interrupt; disable
// split mode; select internal timebase
CKCON |= 0x10; // Timer2 uses SYSCLK as its timebase
TMR2RL = -counts; // Init reload values
TMR2 = TMR2RL; // Init Timer2 with reload value
ET2 = 1; // enable Timer2 interrupts
TR2 = 1; // start Timer2
}
//------------------------------------------------------------------------------------
// Timer3_Init
//------------------------------------------------------------------------------------
//
// Configure the Timer to overflow without interrupts
// The overflow will be used in the wait function
//
void Timer3_Init (int count)
{
TMR3CN = 0x00; // STOP Timer3; Clear TF3H and TF3L;
// disable low-byte interrupt; disable
// split mode; select internal timebase
CKCON |= 0x40; // Timer3 uses SYSCLK as its timebase
TMR3RL = -count; // Init reload values
TMR3 = TMR3RL; // Init Timer3 with reload value
EIE1 &= 0x7F; // disable Timer3 interrupts
TMR3CN |= 0x01; // start Timer3
}
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------
// LCDrefresh is triggered on a Timer2 Overflow
// Takes what is in the LCD bar bits and shift them into the two 74HC595
// shift registers depending on the COM cycle; The most signficant
// LCD pin (pin 16) gets shifted out first; Only 15 bits get shifted each
// COM cycle;
void LCDrefresh_ISR (void) interrupt 5
{
int i = 0;
if (com_cycle == 1)
{
SER = 1 ^ com_invert; Strobe(); // non-existent segment
SER = D6A ^ com_invert; Strobe();
SER = 1 ^ com_invert; Strobe(); // non-existent segment
SER = D5A ^ com_invert; Strobe();
SER = 1 ^ com_invert; Strobe(); // non-existent segment
SER = D4A ^ com_invert; Strobe();
SER = 1 ^ com_invert; Strobe(); // non-existent segment
SER = D3A ^ com_invert; Strobe();
SER = 1 ^ com_invert; Strobe(); // non-existent segment
SER = D2A ^ com_invert; Strobe();
SER = 1 ^ com_invert; Strobe(); // non-existent segment
SER = D1A ^ com_invert; Strobe();
SER = 1 ^ com_invert; Strobe(); // non-existent segment
SER = 1 ^ com_invert; Strobe(); // non-existent segment
SER = 1 ^ com_invert; Strobe(); // non-existent segment
RCLK = 1; // put shifted data to LCD - rising edge
for (i=0; i<PULSE_LENGTH; i++); // keep clock high for a while
RCLK = 0; // turn off clock
P1MDIN &= ~0x80; // configure COM4 to ANALOG_IN;
P1MDIN |= 0x10; // and COM1 to digital
P1MDOUT &= ~0x80; // make COM4 an open-drain
P1MDOUT |= 0x10; // make COM1 a push-pull
COM4 = 1; // set COM4 to high impedance
COM1 = 1 ^ com_invert; // start the COM1 cycle
com_cycle = 2; // next state
}
else if (com_cycle == 2)
{
SER = D6B ^ com_invert; Strobe();
SER = D6F ^ com_invert; Strobe();
SER = D5B ^ com_invert; Strobe();
SER = D5F ^ com_invert; Strobe();
SER = D4B ^ com_invert; Strobe();
SER = D4F ^ com_invert; Strobe();
SER = D3B ^ com_invert; Strobe();
SER = D3F ^ com_invert; Strobe();
SER = D2B ^ com_invert; Strobe();
SER = D2F ^ com_invert; Strobe();
SER = D1B ^ com_invert; Strobe();
SER = D1F ^ com_invert; Strobe();
SER = 1 ^ com_invert; Strobe(); // non-existent segment
SER = 1 ^ com_invert; Strobe(); // non-existent segment
SER = 1 ^ com_invert; Strobe(); // non-existent segment
RCLK = 1; // put shifted data to LCD - rising edge
for (i=0; i<PULSE_LENGTH; i++); // keep clock high for a while
RCLK = 0; // turn off clock
P1MDIN &= ~0x10; // configure COM1 to ANALOG_IN;
P1MDIN |= 0x20; // and COM2 to digital
P1MDOUT &= ~0x10; // make COM1 an open-drain
P1MDOUT |= 0x20; // make COM2 a push-pull
COM1 = 1; // set COM1 to high impedance
COM2 = 1 ^ com_invert; // start the COM2 cycle
com_cycle = 3; // next state
}
else if (com_cycle == 3)
{
SER = D6C ^ com_invert; Strobe();
SER = D6G ^ com_invert; Strobe();
SER = D5C ^ com_invert; Strobe();
SER = D5G ^ com_invert; Strobe();
SER = D4C ^ com_invert; Strobe();
SER = D4G ^ com_invert; Strobe();
SER = D3C ^ com_invert; Strobe();
SER = D3G ^ com_invert; Strobe();
SER = D2C ^ com_invert; Strobe();
SER = D2G ^ com_invert; Strobe();
SER = D1C ^ com_invert; Strobe();
SER = D1G ^ com_invert; Strobe();
SER = 1 ^ com_invert; Strobe(); // non-existent segment
SER = 1 ^ com_invert; Strobe(); // non-existent segment
SER = 1 ^ com_invert; Strobe(); // non-existent segment
RCLK = 1; // put shifted data to LCD - rising edge
for (i=0; i<PULSE_LENGTH; i++); // keep clock high for a while
RCLK = 0; // turn off clock
P1MDIN &= ~0x20; // configure COM2 to ANALOG_IN;
P1MDIN |= 0x40; // and COM3 to digital
P1MDOUT &= ~0x20; // make COM2 an open-drain
P1MDOUT |= 0x40; // make COM3 a push-pull
COM2 = 1; // set COM2 to high impedance
COM3 = 1 ^ com_invert; // start the COM3 cycle
com_cycle = 4; // next state
}
else if (com_cycle == 4)
{
SER = D6D ^ com_invert; Strobe();
SER = D6E ^ com_invert; Strobe();
SER = D5D ^ com_invert; Strobe();
SER = D5E ^ com_invert; Strobe();
SER = D4D ^ com_invert; Strobe();
SER = D4E ^ com_invert; Strobe();
SER = D3D ^ com_invert; Strobe();
SER = D3E ^ com_invert; Strobe();
SER = D2D ^ com_invert; Strobe();
SER = D2E ^ com_invert; Strobe();
SER = D1D ^ com_invert; Strobe();
SER = D1E ^ com_invert; Strobe();
SER = 1 ^ com_invert; Strobe(); // non-existent segment
SER = 1 ^ com_invert; Strobe(); // non-existent segment
SER = 1 ^ com_invert; Strobe(); // non-existent segment
RCLK = 1; // put shifted data to LCD - rising edge
for (i=0; i<PULSE_LENGTH; i++); // keep clock high for a while
RCLK = 0; // turn off clock
P1MDIN &= ~0x40; // configure COM3 to ANALOG_IN;
P1MDIN |= 0x80; // and COM4 to digital
P1MDOUT &= ~0x40; // make COM3 an open-drain
P1MDOUT |= 0x80; // make COM4 a push-pull
COM3 = 1; // set COM3 to high impedance
COM4 = 1 ^ com_invert; // start the COM4 cycle
com_cycle = 1; // next state
com_invert = com_invert ^ 1; // toggle com_invert
}
TF2H = 0; // clear TF2
} // end LCDrefresh_ISR
//-----------------------------------------------------------------------------
// Strobe
//-----------------------------------------------------------------------------
//
// Strobe is used to clock the data into the 74HC595 shift registers
//
void Strobe()
{
int i = 0;
SRCLK = 1;
for (i = 0; i < PULSE_LENGTH; i++); // wait a few cycles
SRCLK = 0;
for (i = 0; i < PULSE_LENGTH; i++); // wait a few cycles
}
//-----------------------------------------------------------------------------
// wait_one_msec
//-----------------------------------------------------------------------------
//
// Assumes Timer3 overflows once every 500 usec
//
void wait_one_ms(unsigned int count)
{
count = count * 2; // overflows once every 500 usec
// so double that is 1 ms
TMR3CN &= ~0x80; // Clear Timer3 overflow flag
TMR3 = TMR3RL;
TMR3CN = 0x04; // Start Timer3
while (count--)
{
while (!(TMR3CN & 0x80)) {} // wait for overflow
TMR3CN &= ~0x80; // clear overflow indicator
}
TMR3CN &= ~0x04; // Stop Timer3
}
//-----------------------------------------------------------------------------
// LCD functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// putchar
//-----------------------------------------------------------------------------
//
// putchar only handles the digit components on the LCD screen.
// This functions shifts the digit values to the left, shifting out the
// left-most digit. This function has 3 potential actions based on the input:
//
// 1. Any input whose ASCII code is between 0 and 127 gets translated
// according to the translation table above
//
// 2. Any input whose ASCII code is between 128 and 255 is directly sent to
// the LCD. The lower 7 bits indicate which of the seven segments are lit.
//
// 3. Passing a newline char '\n' to this function clears all 6 digits
//
// This function, unlike standard putchar, does not have any error return msgs.
//
// This function will not cause an interrupt to force output. The input char
// will be displayed on the screen on the next refresh cycle
char putchar(char charIN)
{
unsigned char iter = 0;
if (charIN != '\n') // not a new line
{
if ((charIN & 0x80) == 0) { // translation necesssary
charIN = translation_table [charIN]; } // quick lookup
EA = 0; // prevent partial display
for (iter = 0; iter < 5; iter++) { // shift the digits left
LCD_digits[iter] = LCD_digits[iter+1]; }
LCD_digits[5] = charIN; // new digit is rightmost
EA = 1; // enable interrupts again
}
else // input is a newline
{
EA = 0; // disable interrupts
for (iter = 0; iter < 6; iter++) {
LCD_digits[iter] = 0xFF; } // clear all digits
EA = 1; // enable interrupts
}
if (charIN == 0xFF) { // couldn't interpret OR space
charIN = ' '; } // return space
return charIN; // just like putchar
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -