热度 1|||
/* Port 5 Output Register */上述代码将一个单字节赋值给PO5,这是微控制器输出端口的地址。然后将另一个字节赋值给相同的可以逐位访问的存储器地址。
__no_init volatile __io union
{
unsigned char PO5;
struct
{
unsigned char bit0 : 1;
unsigned char bit1 : 1;
unsigned char bit2 : 1;
unsigned char bit3 : 1;
unsigned char bit4 : 1;
unsigned char bit5 : 1;
unsigned char bit6 : 1;
unsigned char bit7 : 1;
} PO5_bit;
}
/* Portable bit-set and bit-clear macros. */
#define BIT_SET(sfr,bitmask) sfr |= (bitmask)
#define BIT_CLR(sfr,bitmask) sfr &=~ (bitmask)
#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80
example: BIT_SET(PO5,BIT0); BIT_CLR(PO5,BIT6);
#define SPI_CS PO5_bit.bit4 // PO5_bit.bit4 = active-low CS—chip select用以上宏和数据结构可以单独置位及复位每个IO口,命令如下:
#define SPI_MOSI PO5_bit.bit5 // PO5_bit.bit5 = MOSI—master out slave in,
// data to MAX7456
#define SPI_MISO PI5_bit.bit7 // PO5_bit.bit7 = MISO—master in slave out,
// data from MAX7456
#define SPI_CK PO5_bit.bit6 // PO5_bit.bit6 = SCK - SPI clock
/**************************************************************************************
* spiWriteReg
*
* Writes to an 8-bit register with the SPI port
**************************************************************************************/
void spiWriteReg(const unsigned char regAddr, const unsigned char regData)
{
unsigned char SPICount; // Counter used to clock out the data
unsigned char SPIData; // Define a data structure for the SPI data
SPI_CS = 1; // Make sure we start with active-low CS high
SPI_CK = 0; // and CK low
SPIData = regAddr; // Preload the data to be sent with Address
SPI_CS = 0; // Set active-low CS low to start the SPI cycle
// Although SPIData could be implemented as an "int",
// resulting in one
// loop, the routines run faster when two loops
// are implemented with
// SPIData implemented as two "char"s.
for (SPICount = 0; SPICount < 8; SPICount++) // Prepare to clock out the Address byte
{
if (SPIData & 0x80) // Check for a 1
SPI_MOSI = 1; // and set the MOSI line appropriately
else
SPI_MOSI = 0;
SPI_CK = 1; // Toggle the clock line
SPI_CK = 0;
SPIData <<= 1; // Rotate to get the next bit
} // and loop back to send the next bit
// Repeat for the Data byte
SPIData = regData; // Preload the data to be sent with Data
for (SPICount = 0; SPICount < 8; SPICount++)
{
if (SPIData & 0x80)
SPI_MOSI = 1;
else
SPI_MOSI = 0;
SPI_CK = 1;
SPI_CK = 0;
SPIData <<= 1;
}
SPI_CS = 1;
SPI_MOSI = 0;
}
/**************************************************************************************
* spiReadReg
*
* Reads an 8-bit register with the SPI port.
* Data is returned.
**************************************************************************************/
unsigned char spiReadReg (const unsigned char regAddr)
{
unsigned char SPICount; // Counter used to clock out the data
unsigned char SPIData;
SPI_CS = 1; // Make sure we start with active-low CS high
SPI_CK = 0; // and CK low
SPIData = regAddr; // Preload the data to be sent with Address and Data
SPI_CS = 0; // Set active-low CS low to start the SPI cycle
for (SPICount = 0; SPICount < 8; SPICount++) // Prepare to clock out the Address and Data
{
if (SPIData & 0x80)
SPI_MOSI = 1;
else
SPI_MOSI = 0;
SPI_CK = 1;
SPI_CK = 0;
SPIData <<= 1;
} // and loop back to send the next bit
SPI_MOSI = 0; // Reset the MOSI data line
SPIData = 0;
for (SPICount = 0; SPICount < 8; SPICount++) // Prepare to clock in the data to be read
{
SPIData <<=1; // Rotate the data
SPI_CK = 1; // Raise the clock to clock the data out of the MAX7456
SPIData += SPI_MISO; // Read the data bit
SPI_CK = 0; // Drop the clock ready for the next bit
} // and loop back
SPI_CS = 1; // Raise CS
return ((unsigned char)SPIData); // Finally return the read data
}
/**************************************************************************************
* spiWriteRegAutoIncr
*
* Writes to an 8-bit register with the SPI port using the MAX7456's autoincrement mode
**************************************************************************************/
void spiWriteRegAutoIncr(const unsigned char regData)
{
unsigned char SPICount; // Counter used to clock out the data
unsigned char SPIData; // Define a data structure for the SPI data.
SPI_CS = 1; // Make sure we start with active-low CS high
SPI_CK = 0; // and CK low
SPIData = regData; // Preload the data to be sent with Address and Data
SPI_CS = 0; // Set active-low CS low to start the SPI cycle
for (SPICount = 0; SPICount < 8; SPICount++) // Prepare to clock out the Address and Data
{
if (SPIData & 0x80)
SPI_MOSI = 1;
else
SPI_MOSI = 0;
SPI_CK = 1;
SPI_CK = 0;
SPIData <<= 1;
} // and loop back to send the next bit
SPI_MOSI = 0; // Reset the MOSI data line
}
extern volatile unsigned char data[DATA_BUF_LENGTH];调用程序时,data[]包含显示存储器内容,格式如下:
DATA_BUF_LENGTH = 968
data[0] = ignored (contains a command byte used by the EV kit GUI software)自动递增模式通过写0xFF结束,所以该模式下不能向显示寄存器写0xFF。如果需要写OxFF,可以采用单字节写指令。
data[1] = character byte 1
data[2] = attribute byte 1
data[3] = character byte 2
data[4] = attribute byte 2
etc.
/**************************************************************************************
* spiWriteCM
*
* Writes to the Display Memory (960 bytes) from "data" extern.
* 960 = 16 rows × 30 columns × 2 planes {char vs. attr} screen-position-indexed memory
**************************************************************************************/
void spiWriteCM() // On entry: global data[1..960]
// contains char+attr bytes
// (optionally terminated by 0xFF data)
// First, write data[1,3,5,...] Character plane;
// MAX7456 WriteReg(0x05,0x41)
// "Character Memory Address High";
// 0x02:Attribute bytes;
// 0x01:character memory address msb
{
volatile unsigned int Index = 0x0001; // Index for lookup into
// data[1..960]
spiWriteReg(DM_ADDRH_WRITE,0x00); // initialise the Display Memory high-byte
spiWriteReg(DM_ADDRL_WRITE,0x00); // and the low-byte
spiWriteReg(DM_MODE_WRITE ,0x41); // MAX7456 WriteReg(0x04,0x41) "Display Memory Mode";
// 0x40:Perform 8-bit operation; 0x01:AutoIncrement
Do // Loop to write the character data
{
if (data[Index] == 0xFF) { // Check for the break character
break; } // and finish if found
spiWriteRegAutoIncr(data[Index]); // Write the character
Index += 2; // Increment the index to the next character,
// skipping over the attribute
} while(Index < 0x03C1); // 0x03C1 = 961
// and loop back to send the next character
spiWriteRegAutoIncr(0xFF); // Write the "escape character" to end AutoIncrement
// mode
spiWriteReg(DM_ADDRH_WRITE,0x02); // Second, write data[2,4,6,...]
// Attribute plane; MAX7456
// WriteReg(0x05,0x41)
// "Character Memory Address High";
// 0x02:Attribute bytes; 0x01:character memory address
// msb
spiWriteReg(DM_ADDRL_WRITE,0x00);
spiWriteReg(DM_MODE_WRITE,0x41); // MAX7456 WriteReg(0x04,0x41) "Character Memory
// Mode"; 0x40:Perform 8-bit operation; 0x01:Auto-
// Increment
Index = 0x0002;
do
{
if (data[Index] == 0xFF)
break;
spiWriteRegAutoIncr(data[Index]);
Index += 2;
} while(Index < 0x03C1);
spiWriteRegAutoIncr(0xFF);
}
/**************************************************************************************
* spiWriteFM
*
* Writes to the Character Memory (54 bytes) from "data" extern
**************************************************************************************/
void spiWriteFM()
{
unsigned char Index;
spiWriteReg(VIDEO_MODE_0_WRITE,spiReadReg
(VIDEO_MODE_0_READ) & 0xF7); // Clear bit 0x08 to DISABLE the OSD display
spiWriteReg(FM_ADDRH_WRITE,data[1]); // Write the address of the character to be written
// MAX7456 glyph tile definition
// length = 0x36 = 54 bytes
// MAX7456 64-byte Shadow RAM accessed
// through FM_DATA_.. FM_ADDR.. contains a single
// character/glyph-tile shape
for(Index = 0x00; Index < 0x36; Index++)
{
spiWriteReg(FM_ADDRL_WRITE,Index); // Write the address within the shadow RAM
spiWriteReg(FM_DATA_IN_WRITE,data[Index + 2]); // Write the data to the shadow RAM
}
spiWriteReg(FM_MODE_WRITE, 0xA0); // MAX7456 "Font Memory Mode" write 0xA0 triggers
// copy from 64-byte Shadow RAM to NV array.
while ((spiReadReg(STATUS_READ) & 0x20) != 0x00); // Wait while NV Memory status is BUSY
// MAX7456 0xA0 status bit 0x20: NV Memory Status
// Busy/~Ready
}
/**************************************************************************************
* spiWriteRegAutoIncr
*
* Writes to an 8-bit register with the SPI port by using the MAX7456's autoincrement mode
**************************************************************************************/
// MAX7456 VIDEO_MODE_0 register
#define VIDEO_MODE_0_WRITE 0x00
#define VIDEO_MODE_0_READ 0x80
#define VIDEO_MODE_0_40_PAL 0x40
#define VIDEO_MODE_0_20_NoAutoSync 0x20
#define VIDEO_MODE_0_10_SyncInt 0x10
#define VIDEO_MODE_0_08_EnOSD 0x08
#define VIDEO_MODE_0_04_UpdateVsync 0x04
#define VIDEO_MODE_0_02_Reset 0x02
#define VIDEO_MODE_0_01_EnVideo 0x01
// VIDEO MODE 0 bitmap
#define NTSC 0x00
#define PAL 0x40
#define AUTO_SYNC 0x00
#define EXT_SYNC 0x20
#define INT_SYNC 0x30
#define OSD_EN 0x08
#define VERT_SYNC_IMM 0x00
#define VERT_SYNC_VSYNC 0x04
#define SW_RESET 0x02
#define BUF_EN 0x00
#define BUF_DI 0x01
// MAX7456 VIDEO_MODE_1 register
#define VIDEO_MODE_1_WRITE 0x01
#define VIDEO_MODE_1_READ 0x81
// MAX7456 DM_MODE register
#define DM_MODE_WRITE 0x04
#define DM_MODE_READ 0x84
// MAX7456 DM_ADDRH register
#define DM_ADDRH_WRITE 0x05
#define DM_ADDRH_READ 0x85
// MAX7456 DM_ADDRL register
#define DM_ADDRL_WRITE 0x06
#define DM_ADDRL_READ 0x87
// MAX7456 DM_CODE_IN register
#define DM_CODE_IN_WRITE 0x07
#define DM_CODE_IN_READ 0x87
// MAX7456 DM_CODE_OUT register
#define DM_CODE_OUT_READ 0xB0
// MAX7456 FM_MODE register
#define FM_MODE_WRITE 0x08
#define FM_MODE_READ 0x88
// MAX7456 FM_ADDRH register
#define FM_ADDRH_WRITE 0x09
#define FM_ADDRH_READ 0x89
// MAX7456 FM_ADDRL register
#define FM_ADDRL_WRITE 0x0A
#define FM_ADDRL_READ 0x8A
// MAX7456 FM_DATA_IN register
#define FM_DATA_IN_WRITE 0x0B
#define FM_DATA_IN_READ 0x8B
// MAX7456 FM_DATA_OUT register
#define FM_DATA_OUT_READ 0xC0
// MAX7456 STATUS register
#define STATUS_READ 0xA0
#define STATUS_40_RESET_BUSY 0x40
#define STATUS_20_NVRAM_BUSY 0x20
#define STATUS_04_LOSS_OF_SYNC 0x04
#define STATUS_02_PAL_DETECTED 0x02
#define STATUS_01_NTSC_DETECTED 0x01
// MAX7456 requires clearing OSD Black Level
// register bit 0x10 after reset
#define OSDBL_WR 0x6C
#define OSDBL_RD 0xEC
#define OSDBL_10_DisableAutoBlackLevel 0x10