Some projects require mirroring of fonts or images. This section will teach you the algorithm.
The essence of this algorithm is:
A 16x16 dot matrix image or font has 16 lines, each line has 2 bytes. If these 2 bytes are regarded as a 16-bit int data, then the data needs to be reversed from the original order of high bits on the left and low bits on the right. This program does not merge the 2 bytes into an int data, but directly reverses the order of high and low bits in a byte data, and then swaps the first byte data with the second byte data.
An 8x16 dot matrix image or font has 16 lines, each line has 1 byte, and the data is reversed from the original order of high bits on the left and low bits on the right.
For details, please see the source code.
(1) Hardware platform:
Based on Zhu Zhaoqi 51 single-chip microcomputer learning board.
(2) Function: After the machine is powered on, the four characters "Mantou V5" and the four characters "Mantou V5" on the right side after being mirrored are displayed from top to bottom.
(3) The source code is explained as follows:
#include "REG52.H"
sbit LCDCS_dr = P1^6; //chip select line
sbit LCDSID_dr = P1^7; //Serial data line
sbit LCDCLK_dr = P3^2; //Serial clock line
sbit LCDRST_dr = P3^4; //reset line
void SendByteToLcd(unsigned char ucData); //Send a byte of data to the LCD module
void SPIWrite(unsigned char ucWData, unsigned char ucWRS); //Simulate SPI to send a byte of command or data to the underlying driver of the LCD module
void WriteCommand(unsigned char ucCommand); //Send a byte command to the LCD module
void LCDWriteData(unsigned char ucData); //Send one byte of data to the LCD module
void LCDInit(void); //Initialization function including LCD module reset
void display_lattice(unsigned int x,unsigned int y,const unsigned char *ucArray,unsigned char ucFbFlag,unsigned int x_amount,unsigned int y_amount); //Display any lattice function
void display_clear(void); // Clear the screen
void hz1616_mirror(const unsigned char *p_ucHz,unsigned char *p_ucResult); //Mirror the 16x16 dot matrix font
void hz816_mirror(const unsigned char *p_ucHz,unsigned char *p_ucResult); //Mirror the 8x16 dot matrix font
void delay_short(unsigned int uiDelayshort); //Delay
code unsigned char Hz1616_man[]= /* horizontal modulus 16X16 dot matrix*/
{
0x21,0xF8,0x21,0x08,0x21,0xF8,0x3D,0x08,0x45,0xF8,0x48,0x00,0x83,0xFC,0x22,0x94,
0x23,0xFC,0x20,0x00,0x21,0xF8,0x20,0x90,0x28,0x60,0x30,0x90,0x23,0x0E,0x00,0x00,
};
code unsigned char Hz1616_tou[]= /*Head horizontal modulus 16X16 dot matrix*/
{
0x00,0x80,0x10,0x80,0x0C,0x80,0x04,0x80,0x10,0x80,0x0C,0x80,0x08,0x80,0x00,0x80,
0xFF,0xFE,0x00,0x80,0x01,0x40,0x02,0x20,0x04,0x30,0x08,0x18,0x10,0x0C,0x20,0x08,
};
code unsigned char Zf816_V[]= /*V horizontal modulus 8x16 dot matrix*/
{
0x00,0x00,0x00,0xE7,0x42,0x42,0x44,0x24,0x24,0x28,0x28,0x18,0x10,0x10,0x00,0x00,
};
code unsigned char Zf816_5[]= /*5 horizontal modulus 8x16 dot matrix*/
{
0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x58,0x64,0x02,0x02,0x42,0x44,0x38,0x00,0x00,
};
unsigned char ucBufferResult[32]; //Used to temporarily store the character array after the conversion is completed
void main()
{
LCDInit(); // Initialize 12864 including the reset of the LCD module
display_clear(); // Clear the screen
display_lattice(0,0,Hz1616_man,0,2,16); //Display the word <馒> before mirroring
hz1616_mirror(Hz1616_man,ucBufferResult); //Mirror the character <馒> and put it into the temporary variable ucBufferResult.
display_lattice(1,0,ucBufferResult,0,2,16); //Display the mirrored word <馒>
display_lattice(0,16,Hz1616_tou,0,2,16); //Display the word
before the mirrorhz1616_mirror(Hz1616_tou,ucBufferResult); //Mirror the
character and put it into the ucBufferResult temporary variable.display_lattice(1,16,ucBufferResult,0,2,16); //Display the mirrored
display_lattice(8,0,Zf816_V,0,1,16); //Display the characters before mirroring
hz816_mirror(Zf816_V,ucBufferResult); //Mirror the characters and put them into the temporary variable ucBufferResult.
display_lattice(9,0,ucBufferResult,0,1,16); //Display the mirrored characters
display_lattice(8,16,Zf816_5,0,1,16); //Display the character <5> before the mirror
hz816_mirror(Zf816_5,ucBufferResult); //Mirror the <5> character and put it into the ucBufferResult temporary variable.
display_lattice(9,16,ucBufferResult,0,1,16); //Display the mirrored character <5>
while(1)
{
;
}
}
void display_clear(void) // Clear the screen
{
unsigned char x,y;
WriteCommand(0x34); //Display buffer command
WriteCommand(0x34); //Display buffer off command is intentionally written twice, for fear that it will not work once. This is because I refer to a driver from a certain manufacturer that is also written in this way.
y=0;
while(y<32) //y axis ranges from 0 to 31
{
WriteCommand(y+0x80); //vertical address
WriteCommand(0x80); //Horizontal address
for(x=0;x<32;x++) //256 horizontal points, 32 bytes
{
LCDWriteData(0x00);
}
y++;
}
WriteCommand(0x36); //Open display buffer command
}
/* Note 1:
* The essence of 16x16 dot matrix mirror:
* A 16x16 dot matrix has 16 rows, each row has 2 bytes. If these 2 bytes are regarded as a 16-bit int data,
* Then the data is reversed from the original order of high bits on the left and low bits on the right. This program does not convert the 2 bytes
* Instead of merging them into an int data, the high and low bit order is directly reversed within a byte of data, and then the first byte of data is swapped with the second byte of data.
*/
void hz1616_mirror(const unsigned char *p_ucHz,unsigned char *p_ucResult) //Function to mirror the 16x16 dot matrix font library
{
unsigned char a;
unsigned char b;
unsigned char c;
unsigned char d;
for(a=0;a<16;a++) //Here 16 means there are 16 rows. Each row has 2 bytes. Consider each byte as a column. Here, we first reverse the order of the bytes in the first column from the original high bits on the left to the low bits on the right, which is equivalent to a mirror image.
{
b=p_ucHz[a*2+0]; //The 2 here means that there are 2 columns of bytes in each row of the 16x16 dot matrix, and 0 means starting from the 1st column.
c=0;
for(d=0;d<8;d++) //switch the order of a byte
{
c=c>>1;
if((b&0x80)==0x80)
{
c=c|0x80;
}
b=b<<1;
}
p_ucResult[a*2+1]=c; //Note that because it is a mirror image, the bytes in reverse order should be swapped from the first column to the second column
}
for(a=0;a<16;a++) //Here 16 means there are 16 rows. Each row has 2 bytes. Consider each byte as a column. Here, we first reverse the order of the bytes in the second column from the original high bits on the left to the low bits on the right, which is equivalent to a mirror image.
{
b=p_ucHz[a*2+1]; //The 2 here means that there are 2 columns of bytes in each row of the 16x16 dot matrix, and 1 means starting from the 2nd column.
c=0;
for(d=0;d<8;d++) //switch the order of a byte
{
c=c>>1;
if((b&0x80)==0x80)
{
c=c|0x80;
}
b=b<<1;
}
p_ucResult[a*2+0]=c; //Note that because it is a mirror image, the bytes in reverse order should be swapped from the second column to the first column
}
}
/* Note 2:
* The essence of 8x16 dot matrix mirror:
* 8x16 dot matrix has 16 rows, each row has 1 byte, the data is reversed from the original order of high bits on the left and low bits on the right.
*/
void hz816_mirror(const unsigned char *p_ucHz,unsigned char *p_ucResult) //Function to mirror the 8x16 dot matrix font library
{
unsigned char a;
unsigned char b;
unsigned char c;
unsigned char d;
for(a=0;a<16;a++) //Here 16 means there are 16 rows. Each row has 1 byte. Here, we first reverse the order of the bytes in each row from the original left side being high bits and the right side being low bits, which is equivalent to mirroring.
{
b=p_ucHz[a*1+0]; //Here 1 means that there is 1 column of bytes in each row of the 8x16 dot matrix, and 0 means starting from the 1st column.
c=0;
for(d=0;d<8;d++) //switch the order of a byte
{
c=c>>1;
if((b&0x80)==0x80)
{
c=c|0x80;
}
b=b<<1;
}
p_ucResult[a*1+0]=c; //Note that since each row has only one column, there is no need to swap the first column with the second column like in a 16x16 matrix.
}
}
/* Note 3: The core function of this section. Readers should especially understand the display relationship between x_amount and y_amount.
* The first and second parameters x and y are coordinate systems. The range of x is 0 to 15, and the range of y is 0 to 31.
* The third parameter *ucArray is the array of fonts.
* The fourth parameter ucFbFlag is the reverse display flag. 0 represents normal display, 1 represents reverse display.
* The 5th and 6th parameters x_amount and y_amount represent the number of bytes in the horizontal direction and the number of bytes in the vertical direction of the font array respectively.
*/
void display_lattice(unsigned int x,unsigned int y,const unsigned char *ucArray,unsigned char ucFbFlag,unsigned int x_amount,unsigned int y_amount)
{
unsigned int j=0;
unsigned int i=0;
unsigned char ucTemp;
WriteCommand(0x34); //Display buffer command
WriteCommand(0x34); //Display buffer off command is intentionally written twice, for fear that it will not work once. This is because I refer to a driver from a certain manufacturer that is also written in this way.
for(j=0;j
{
WriteCommand(y+j+0x80); //vertical address
WriteCommand(x+0x80); //Horizontal address
for(i=0;i
{
ucTemp=ucArray[j*x_amount+i];
if(ucFbFlag==1) //Highlight
{
ucTemp=~ucTemp;
}
LCDWriteData(ucTemp);
// delay_short(30000); //Remove the delay function in the previous section to speed up the screen refresh
}
}
WriteCommand(0x36); //Open display buffer command
}
void SendByteToLcd(unsigned char ucData) //Send a byte of data to the LCD module
{
unsigned char i;
for ( i = 0; i < 8; i++ )
{
if ( (ucData << i) & 0x80 )
{
LCDSID_dr = 1;
}
else
{
LCDSID_dr = 0;
}
LCDCLK_dr = 0;
LCDCLK_dr = 1;
}
}
void SPIWrite(unsigned char ucWData, unsigned char ucWRS) //Simulate SPI to send a byte of command or data to the underlying driver of the LCD module
{
SendByteToLcd( 0xf8 + (ucWRS << 1) );
SendByteToLcd(ucWData & 0xf0);
SendByteToLcd( (ucWData << 4) & 0xf0);
}
void WriteCommand(unsigned char ucCommand) //Send a byte command to the LCD module
{
LCDCS_dr = 0;
LCDCS_dr = 1;
SPIWrite(ucCommand, 0);
delay_short(90);
}
void LCDWriteData(unsigned char ucData) //Send one byte of data to the LCD module
{
LCDCS_dr = 0;
LCDCS_dr = 1;
SPIWrite(ucData, 1);
}
void LCDInit(void) //Initialization function including LCD module reset
{
LCDRST_dr = 1; // reset
LCDRST_dr = 0;
LCDRST_dr = 1;
}
void delay_short(unsigned int uiDelayShort) //delay function
{
unsigned int i;
for(i=0;i
{
;
}
}
Closing remarks:
Careful netizens will definitely find that this 12864 LCD screen generally has a problem. It cannot fully display as desired in the x and y directions of the coordinate axis with one dot matrix. For example, the horizontal direction is at least one byte of 8 dots, and the 1st and 2nd rows and the 3rd and 4th rows cannot be seamlessly displayed. If I want to display half of the Chinese characters in the 2nd row and half in the 3rd row, is it possible? Of course. But we need to write an additional algorithm program. How is this algorithm program written? For details, please listen to the next analysis - the algorithm program that allows fonts to be seamlessly displayed across regions in the LCD screen.
Previous article:Section 72: Algorithm program for rotating the font 90 degrees clockwise on the LCD screen
Next article:Section 74: Algorithm program for seamlessly displaying fonts across regions on LCD screens
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- The best video to introduce you to Matter is here! Check it out now.
- Design summary of RGB to VGA module
- "The domineering hacker changed my outline" and the fan hacked the author's account to write a new plot of 20,000 words because he thought the author's writing was too bad.
- The basic working principle of electromagnetic slip clutch
- Are supercapacitors close to our lives?
- EEPROM address problem
- How many ohms are the resistors with silk screen 010 and 300?
- Help: After selecting the package in AD09, no corresponding description appears
- TI HVI Power Technology Detailed 2019
- When the op amp is used as a voltage follower, what is the role of the resistor and capacitor connected to the negative feedback terminal?