"); //-->
代码;
lcd_drive.c
//*****************************************************************************
//
// File........: LCD_driver.c
//
// Author(s)...: ATMEL Norway
//
// Target(s)...: ATmega169
//
// Compiler....: AVR-GCC 3.3.1; avr-libc 1.0
//
// Description.: Functions used to control the AVR Butterfly LCD
//
// Revisions...: 1.0
//
// YYYYMMDD - VER. - COMMENT - SIGN.
//
// 20021015 - 1.0 - Written for STK502 - JLL
// 20030116 - 2.0 - Code adapted to AVR Butterfly - KS
// 20031009 port to avr-gcc/avr-libc - M.Thomas
//
//*****************************************************************************
#define REDUCED
// Include files.
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/interrupt.h>
// mt - for gButtonTimeout
// #include "button.h"
#include "LCD_driver.h"
#ifndef BOOL
#define BOOL char
#define FALSE 0
#define TRUE (!FALSE)
#endif
// Variable from "button.c" to prevent button-bouncing
extern unsigned char gButtonTimeout;
volatile char gAutoPressJoystick = FALSE;
// Used to indicate when the LCD interrupt handler should update the LCD
// mt jw char gLCD_Update_Required = FALSE;
volatile char gLCD_Update_Required = FALSE;
// LCD display buffer (for double buffering).
volatile char LCD_Data[LCD_REGISTER_COUNT];
// Buffer that contains the text to be displayed
// Note: Bit 7 indicates that this character is flashing
volatile char gTextBuffer[TEXTBUFFER_SIZE];
// Only six letters can be shown on the LCD.
// With the gScroll and gScrollMode variables,
// one can select which part of the buffer to show
volatile signed char gScroll;
volatile char gScrollMode;
////Start-up delay before scrolling a string over the LCD
char gLCD_Start_Scroll_Timer = 0;
// The gFlashTimer is used to determine the on/off
// timing of flashing characters
volatile char gFlashTimer = 0;
// Turns on/off the colons on the LCD
char gColon = 0;
// Look-up table used when converting ASCII to
// LCD display data (segment control)
// mt __flash unsigned int LCD_character_table[] =
unsigned int LCD_character_table[] PROGMEM =
{
0x0A51, // '*' (?)
0x2A80, // '+'
0x0000, // ',' (Not defined)
0x0A00, // '-'
0x0A51, // '.' Degree sign
0x0000, // '/' (Not defined)
0x5559, // '0'
0x0118, // '1'
0x1e11, // '2
0x1b11, // '3
0x0b50, // '4
0x1b41, // '5
0x1f41, // '6
0x0111, // '7
0x1f51, // '8
0x1b51, // '9'
0x0000, // ':' (Not defined)
0x0000, // ';' (Not defined)
0x0000, // '<' (Not defined)
0x0000, // '=' (Not defined)
0x0000, // '>' (Not defined)
0x0000, // '?' (Not defined)
0x0000, // '@' (Not defined)
0x0f51, // 'A' (+ 'a')
0x3991, // 'B' (+ 'b')
0x1441, // 'C' (+ 'c')
0x3191, // 'D' (+ 'd')
0x1e41, // 'E' (+ 'e')
0x0e41, // 'F' (+ 'f')
0x1d41, // 'G' (+ 'g')
0x0f50, // 'H' (+ 'h')
0x2080, // 'I' (+ 'i')
0x1510, // 'J' (+ 'j')
0x8648, // 'K' (+ 'k')
0x1440, // 'L' (+ 'l')
0x0578, // 'M' (+ 'm')
0x8570, // 'N' (+ 'n')
0x1551, // 'O' (+ 'o')
0x0e51, // 'P' (+ 'p')
0x9551, // 'Q' (+ 'q')
0x8e51, // 'R' (+ 'r')
0x9021, // 'S' (+ 's')
0x2081, // 'T' (+ 't')
0x1550, // 'U' (+ 'u')
0x4448, // 'V' (+ 'v')
0xc550, // 'W' (+ 'w')
0xc028, // 'X' (+ 'x')
0x2028, // 'Y' (+ 'y')
0x5009, // 'Z' (+ 'z')
0x0000, // '[' (Not defined)
0x0000, // '\' (Not defined)
0x0000, // ']' (Not defined)
0x0000, // '^' (Not defined)
0x0000 // '_'
};
/*****************************************************************************
*
* Function name : LCD_Init
*
* Returns : None
*
* Parameters : None
*
* Purpose : Initialize LCD_displayData buffer.
* Set up the LCD (timing, contrast, etc.)
*
*****************************************************************************/
void LCD_Init (void)
{
LCD_AllSegments(FALSE); // Clear segment buffer.
LCD_CONTRAST_LEVEL(LCD_INITIAL_CONTRAST); //Set the LCD contrast level
// Select asynchronous clock source, enable all COM pins and enable all
// segment pins.
LCDCRB = (1<<LCDCS) | (3<<LCDMUX0) | (7<<LCDPM0);
// Set LCD prescaler to give a framerate of 32,0 Hz
LCDFRR = (0<<LCDPS0) | (7<<LCDCD0);
LCDCRA = (1<<LCDEN) | (1<<LCDAB); // Enable LCD and set low power waveform
//Enable LCD start of frame interrupt
LCDCRA |= (1<<LCDIE);
gLCD_Update_Required = FALSE;
}
/*****************************************************************************
*
* Function name : LCD_WriteDigit(char c, char digit)
*
* Returns : None
*
* Parameters : Inputs
* c: The symbol to be displayed in a LCD digit
* digit: In which digit (0-5) the symbol should be displayed
* Note: Digit 0 is the first used digit on the LCD,
* i.e LCD digit 2
*
* Purpose : Stores LCD control data in the LCD_displayData buffer.
* (The LCD_displayData is latched in the LCD_SOF interrupt.)
*
*****************************************************************************/
void LCD_WriteDigit(char c, char digit)
{
unsigned int seg = 0x0000; // Holds the segment pattern
char mask, nibble;
volatile char *ptr;
char i;
if (digit > 5) // Skip if digit is illegal
return;
//Lookup character table for segmet data
if ((c >= '*') && (c <= 'z'))
{
// c is a letter
if (c >= 'a') // Convert to upper case
c &= ~0x20; // if necessarry
c -= '*';
//mt seg = LCD_character_table[c];
seg = (unsigned int) pgm_read_word(&LCD_character_table[(uint8_t)c]);
}
// Adjust mask according to LCD segment mapping
if (digit & 0x01)
mask = 0x0F; // Digit 1, 3, 5
else
mask = 0xF0; // Digit 0, 2, 4
ptr = LCD_Data + (digit >> 1); // digit = {0,0,1,1,2,2}
for (i = 0; i < 4; i++)
{
nibble = seg & 0x000F;
seg >>= 4;
if (digit & 0x01)
nibble <<= 4;
*ptr = (*ptr & mask) | nibble;
ptr += 5;
}
}
/*****************************************************************************
*
* Function name : LCD_AllSegments(unsigned char input)
*
* Returns : None
*
* Parameters : show - [TRUE;FALSE]
*
* Purpose : shows or hide all all LCD segments on the LCD
*
*****************************************************************************/
void LCD_AllSegments(char show)
{
unsigned char i;
if (show)
show = 0xFF;
// Set/clear all bits in all LCD registers
for (i=0; i < LCD_REGISTER_COUNT; i++)
*(LCD_Data + i) = show;
}
/*****************************************************************************
*
* LCD Interrupt Routine
*
* Returns : None
*
* Parameters : None
*
* Purpose: Latch the LCD_displayData and Set LCD_status.updateComplete
*
*****************************************************************************/
SIGNAL(SIG_LCD)
{
static char LCD_timer = LCD_TIMER_SEED;
char c;
char c_flash;
char flash;
char EOL;
unsigned char i;
#ifndef REDUCED
static char timeout_count;
static char auto_joystick_count;
#endif
c_flash=0; // mt
#ifndef REDUCED
/**************** Button timeout for the button.c, START ****************/
if(!gButtonTimeout)
{
timeout_count++;
if(timeout_count > 3)
{
gButtonTimeout = TRUE;
timeout_count = 0;
}
}
/**************** Button timeout for the button.c, END ******************/
/**************** Auto press joystick for the main.c, START *************/
if(gAutoPressJoystick == AUTO)
{
auto_joystick_count++;
if(auto_joystick_count > 16)
{
gAutoPressJoystick = TRUE;
auto_joystick_count = 15;
}
}
else
auto_joystick_count = 0;
/**************** Auto press joystick for the main.c, END ***************/
#endif
LCD_timer--; // Decreased every LCD frame
if (gScrollMode)
{
// If we are in scroll mode, and the timer has expired,
// we will update the LCD
if (LCD_timer == 0)
{
if (gLCD_Start_Scroll_Timer == 0)
{
gLCD_Update_Required = TRUE;
}
else
gLCD_Start_Scroll_Timer--;
}
}
else
{ // if not scrolling,
// disble LCD start of frame interrupt
// cbi(LCDCRA, LCDIE); //DEBUG
gScroll = 0;
}
EOL = FALSE;
if (gLCD_Update_Required == TRUE)
{
// Duty cycle of flashing characters
if (gFlashTimer < (LCD_FLASH_SEED >> 1))
flash = 0;
else
flash = 1;
// Repeat for the six LCD characters
for (i = 0; i < 6; i++)
{
if ((gScroll+i) >= 0 && (!EOL))
{
// We have some visible characters
c = gTextBuffer[i + gScroll];
c_flash = c & 0x80 ? 1 : 0;
c = c & 0x7F;
if (c == '\0')
EOL = i+1; // End of character data
}
else
c = ' ';
// Check if this character is flashing
if (c_flash && flash)
LCD_WriteDigit(' ', i);
else
LCD_WriteDigit(c, i);
}
// Copy the segment buffer to the real segments
for (i = 0; i < LCD_REGISTER_COUNT; i++)
*(pLCDREG + i) = *(LCD_Data+i);
// Handle colon
if (gColon)
*(pLCDREG + 8) = 0x01;
else
*(pLCDREG + 8) = 0x00;
// If the text scrolled off the display,
// we have to start over again.
if (EOL == 1)
gScroll = -6;
else
gScroll++;
// No need to update anymore
gLCD_Update_Required = FALSE;
}
// LCD_timer is used when scrolling text
if (LCD_timer == 0)
{
/* if ((gScroll <= 0) || EOL)
LCD_timer = LCD_TIMER_SEED/2;
else*/
LCD_timer = LCD_TIMER_SEED;
}
// gFlashTimer is used when flashing characters
if (gFlashTimer == LCD_FLASH_SEED)
gFlashTimer= 0;
else
gFlashTimer++;
}LCD_functions.c
//*****************************************************************************
//
// File........: LCD_functions.c
//
// Author(s)...: ATMEL Norway
//
// Target(s)...: ATmega169
//
// Compiler....: AVR-GCC 3.3.1; avr-libc 1.0
//
// Description.: Additional LCD functions, scrolling text and write data
//
// Revisions...: 1.0
//
// YYYYMMDD - VER. - COMMENT - SIGN.
//
// 20021015 - 1.0 - Created - LHM
// 20030116 - 2.0 - Code adapted to AVR Butterflyup - KS
// 20031009 port to avr-gcc/avr-libc - M.Thomas
//
//*****************************************************************************
#define REDUCED
// Include files
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include "LCD_driver.h"
#include "LCD_functions.h"
#ifndef REDUCED
#include "BCD.h"
// mt only for KEY_* and ST_OPTIONS_DISPLAY* definitions:
#include "main.h"
#endif
#define FALSE 0
#define TRUE (!FALSE)
// mt char CONTRAST = LCD_INITIAL_CONTRAST;
uint8_t CONTRAST = LCD_INITIAL_CONTRAST;
// Start-up delay before scrolling a string over the LCD. "LCD_driver.c"
extern char gLCD_Start_Scroll_Timer;
/****************************************************************************
*
* Function name : LCD_puts_f
*
* Returns : None
*
* Parameters : pFlashStr: Pointer to the string in flash
* scrollmode: Not in use
*
* Purpose : Writes a string stored in flash to the LCD
*
*****************************************************************************/
// mt void LCD_puts_f(char __flash *pFlashStr, char scrollmode)
void LCD_puts_f(const char *pFlashStr, char scrollmode)
{
// char i;
uint8_t i;
while (gLCD_Update_Required); // Wait for access to buffer
// mt: for (i = 0; pFlashStr[i] && i < TEXTBUFFER_SIZE; i++)
for (i = 0; (const char)(pgm_read_byte(&pFlashStr[i])) && i < TEXTBUFFER_SIZE; i++)
{
// mt: gTextBuffer[i] = pFlashStr[i];
gTextBuffer[i] = pgm_read_byte(&pFlashStr[i]);
}
gTextBuffer[i] = '\0';
if (i > 6)
{
gScrollMode = 1; // Scroll if text is longer than display size
gScroll = 0;
gLCD_Start_Scroll_Timer = 3; //Start-up delay before scrolling the text
}
else
{
gScrollMode = 0;
gScroll = 0;
}
gLCD_Update_Required = 1;
}
/****************************************************************************
*
* Function name : LCD_puts
*
* Returns : None
*
* Parameters : pStr: Pointer to the string
* scrollmode: Not in use
*
* Purpose : Writes a string to the LCD
*
*****************************************************************************/
void LCD_puts(char *pStr, char scrollmode)
{
uint8_t i; // char i;
while (gLCD_Update_Required); // Wait for access to buffer
for (i = 0; pStr[i] && i < TEXTBUFFER_SIZE; i++)
{
gTextBuffer[i] = pStr[i];
}
gTextBuffer[i] = '\0';
if (i > 6)
{
gScrollMode = 1; // Scroll if text is longer than display size
gScroll = 0;
gLCD_Start_Scroll_Timer = 3; //Start-up delay before scrolling the text
}
else
{
gScrollMode = 0;
gScroll = 0;
}
gLCD_Update_Required = 1;
}
/****************************************************************************
*
* Function name : LCD_putc
*
* Returns : None
*
* Parameters : digit: Which digit to write on the LCD
* character: Character to write
*
* Purpose : Writes a character to the LCD
*
*****************************************************************************/
// mt void LCD_putc(char digit, char character)
void LCD_putc(uint8_t digit, char character)
{
if (digit < TEXTBUFFER_SIZE)
gTextBuffer[digit] = character;
}
/****************************************************************************
*
* Function name : LCD_Clear
*
* Returns : None
*
* Parameters : None
*
* Purpose : Clear the LCD
*
*****************************************************************************/
void LCD_Clear(void)
{
uint8_t i; // char i;
for (i=0; i<TEXTBUFFER_SIZE; i++)
gTextBuffer[i] = ' ';
}
/****************************************************************************
*
* Function name : LCD_Colon
*
* Returns : None
*
* Parameters : show: Enables the colon if TRUE, disable if FALSE
*
* Purpose : Enable/disable colons on the LCD
*
*****************************************************************************/
void LCD_Colon(char show)
{
gColon = show;
}
/****************************************************************************
*
* Function name : LCD_UpdateRequired
*
* Returns : None
*
* Parameters : update: TRUE/FALSE
* scrollmode: not in use
*
* Purpose : Tells the LCD that there is new data to be presented
*
*****************************************************************************/
void LCD_UpdateRequired(char update, char scrollmode)
{
while (gLCD_Update_Required);
gScrollMode = scrollmode;
gScroll = 0;
gLCD_Update_Required = update;
}
/****************************************************************************
*
* Function name : LCD_FlashReset
*
* Returns : None
*
* Parameters : None
*
* Purpose : This function resets the blinking cycle of a flashing digit
*
*****************************************************************************/
void LCD_FlashReset(void)
{
gFlashTimer = 0;
}
#ifndef REDUCED
/****************************************************************************
*
* Function name : SetContrast
*
* Returns : char ST_state (to the state-machine)
*
* Parameters : char input (from joystick)
*
* Purpose : Adjust the LCD contrast
*
*****************************************************************************/
char SetContrast(char input)
{
static char enter = 1;
char CH, CL;
if (enter)
{
LCD_Clear();
enter = 0;
}
CH = CHAR2BCD2(CONTRAST);
CL = (CH & 0x0F) + '0';
CH = (CH >> 4) + '0';
LCD_putc(0, 'C');
LCD_putc(1, 'T');
LCD_putc(2, 'R');
LCD_putc(3, ' ');
LCD_putc(4, CH);
LCD_putc(5, CL);
LCD_UpdateRequired(TRUE, 0);
if (input == KEY_PLUS)
CONTRAST++;
else if (input == KEY_MINUS)
CONTRAST--;
if (CONTRAST == 255)
CONTRAST = 0;
if (CONTRAST > 15)
CONTRAST = 15;
LCD_CONTRAST_LEVEL(CONTRAST);
if (input == KEY_ENTER)
{
enter = 1;
return ST_OPTIONS_DISPLAY_CONTRAST;
}
return ST_OPTIONS_DISPLAY_CONTRAST_FUNC;
}
#endif
// REDUCEDmain.c
/*
《AVR专题精选》随书例程
3.通信接口使用技巧
项目:使用USI作为主I2C接口
文件:main.c
说明:主程序文件. 在AVR Bufferfly上演示USI做主I2C接口用法
控制EEPROM 24AA00
按键: 上 数据加
下 数据减
左 读取数据
右 写数据
中 随机数据
作者:邵子扬
时间:2012年12月17日
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
#include <stdio.h>
// 系统时钟频率
#define F_CPU 1000000UL
#include <util/delay.h>
#include "LCD_functions.h"
#include "LCD_driver.h"
#include "macromcu.h"
// I2C 接口端口定义
#define SDA E, 5
#define SCL E, 4
// I2C 信号定义
#define I2C_MASTER 0
#define I2C_SLAVE 1
#define I2C_ACK 0
#define I2C_NAK 1
/*
函数说明: I2C初始化
参数说明:
mode: b7654321: not use
b0: 0 master, 1 slave
*/
void I2C_init(char mode, char speed)
{
// I2C 模式
// Master or Slave
if(mode)// Slave
{
}
else // master
{
PINSET(SDA); // Enable pullup on SDA, to set high as released state.
PINSET(SCL); // Enable pullup on SCL, to set high as released state.
PINDIR(SDA, PIN_OUTPUT); // Enable SDA as output.
PINDIR(SCL, PIN_OUTPUT); // Enable SCL as output.
USIDR = 0xFF; // Preload dataregister with "released level" data.
USICR = (0<<USISIE)|(0<<USIOIE)| // Disable Interrupts.
(1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode.
(1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software stobe as counter clock source
(0<<USITC);
USISR = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Clear flags,
(0x0<<USICNT0); // and reset counter.
}
}
// Prepare register value to: Clear flags, and
// set USI to shift 8 bits i.e. count 16 clock edges.
#define tempUSISR_8bit (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|(0x0<<USICNT0)
// Prepare register value to: Clear flags, and
// set USI to shift 1 bit i.e. count 2 clock edges.
#define tempUSISR_1bit (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|(0xE<<USICNT0)
#define TWI_READ_BIT 0 // Bit position for R/W bit in "address byte".
#define TWI_ADR_BITS 1 // Bit position for LSB of the slave address bits in the init byte.
#define TWI_NACK_BIT 0 // Bit position for (N)ACK bit.
// USI 接口发送数据
unsigned char USI_TWI_Master_Transfer(unsigned char temp)
{
USISR = temp;
temp = (0<<USISIE)|(0<<USIOIE)| // Interrupts disabled
(1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode.
(1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software clock strobe as source.
(1<<USITC); // Toggle Clock Port.
do
{
_delay_us(5);
USICR = temp; // Generate positve SCL edge.
while(!PININ(SCL)); // Wait for SCL to go high.
_delay_us(5);
USICR = temp; // Generate negative SCL edge.
}while( !(USISR & (1<<USIOIF)) ); // Check for transfer complete.
_delay_us(5);
temp = USIDR; // Read out data.
USIDR = 0xFF; // Release SDA.
PINDIR(SDA, PIN_OUTPUT); // Enable SDA as output.
return temp; // Return the data from the USIDR
}
// I2C 写一个字节
unsigned char I2C_Master_WriteByte(unsigned char dat)
{
PINCLR(SCL); // Pull SCL LOW.
USIDR = dat; // Setup data.
USI_TWI_Master_Transfer( tempUSISR_8bit ); // Send 8 bits on bus.
/* Clock and verify (N)ACK from slave */
PINDIR(SDA, PIN_INPUT); // Enable SDA as input.
if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) )
return 1;
else
return 0;
}
// I2C 读取一个字节
unsigned char I2C_Master_ReadByte()
{
PINDIR(SDA, PIN_INPUT);
return USI_TWI_Master_Transfer(tempUSISR_8bit);
}
// I2C 发送ACK信号
void I2C_Master_ACK(char ack)
{
if(ack == I2C_ACK)
{
USIDR = 0x00;
}
else
{
USIDR = 0xFF;
}
USI_TWI_Master_Transfer( tempUSISR_1bit ); // Generate ACK/NACK.
}
// I2C 起始信号
void I2C_start()
{
PINSET(SCL); // Release SCL.
while(!PININ(SCL)); // Verify that SCL becomes high.
_delay_us(5);
PINCLR(SDA); // Force SDA LOW.
_delay_us(5);
PINCLR(SCL); // Pull SCL LOW.
PINSET(SDA); // Release SDA.
}
// I2C 停止信号
void I2C_stop()
{
PINCLR(SDA); // Pull SDA low.
PINSET(SCL); // Release SCL.
while(!PININ(SCL)); // Wait for SCL to go high.
_delay_us(5);
PINSET(SDA); // Release SDA.
_delay_us(5);
}
// 按键掩码
#define PINB_MASK ((1<<PINB4)|(1<<PINB6)|(1<<PINB7))
#define PINE_MASK ((1<<PINE2)|(1<<PINE3))
// 读取 AVR Butterfly 按键
unsigned char getkey()
{
unsigned char t;
t = (~PINB) & PINB_MASK;
t |= (~PINE) & PINE_MASK;
return t;
}
unsigned char dat = 0, cnt;
char s[] = " 00";
// HEX 转换为字符
unsigned char hexchr(unsigned char dat)
{
if(dat > 15)
return '0';
if(dat < 10)
return dat + '0';
else
return dat - 10 + 'A';
}
// HEX 转换为字符串
void hexbuf(unsigned char dat, char *buf)
{
buf[0] = hexchr(dat/16);
buf[1] = hexchr(dat%16);
}
// 读取EEPROM地址0数据
unsigned char ReadByte()
{
unsigned char t;
I2C_start(); // 发送起始信号
I2C_Master_WriteByte(0xA0); // 发送设备地址
I2C_Master_WriteByte(0x00); // 发送地址
I2C_start(); // 发送起始信号
I2C_Master_WriteByte(0xA1); // 发送读取命令
t = I2C_Master_ReadByte(); // 读取数据
I2C_Master_ACK(I2C_NAK); // 发送NAK信号
I2C_stop(); // 发送停止信号
return t;
}
// 写入数据到EEPROM地址0
void WriteByte(unsigned char dat)
{
I2C_start(); // 发送起始信号
I2C_Master_WriteByte(0xA0); // 发送设备地址
I2C_Master_WriteByte(0x00); // 发送地址
I2C_Master_WriteByte(dat); // 写入数据
I2C_stop(); // 发送停止信号
}
// 主程序
int main()
{
// IO 初始化
PINDIR(SCL, PIN_OUTPUT);
PINDIR(SDA, PIN_OUTPUT);
PORTB |= PINB_MASK;
PORTE |= PINE_MASK;
// I2C 初始化
I2C_init(0, 0);
// AVR Butterfly LCD初始化
LCD_Init();
// 开中断
sei();
// 显示地址和数据
hexbuf(dat, s+4);
LCD_puts(s, 0);
while(1)
{
_delay_ms(200); // 延时
cnt++;
if(getkey()) // 读取按键
{
switch(getkey())
{
case 0x40://上, 数据递增
dat++;
s[0] = ' ';
break;
case 0x80://下, 数据递减
dat--;
s[0] = ' ';
break;
case 0x04://左, 读取数据
s[0] = 'R';
dat = ReadByte();
break;
case 0x08://右, 写入数据
s[0] = 'W';
WriteByte(dat);
break;
case 0x10://中, 随机数据
//dat = ReadStatus();
//hexbuf(dat, s+2);
dat = cnt;
break;
}
hexbuf(dat, s+4); // 更新显示
LCD_puts(s, 0);
}
}
return 0;
}仿真

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。