| 
              【程序】#include <stm32f10x.h>
 #define RS_0 GPIOB->ODR &= ~GPIO_Pin_1 // 寄存器选择位
 #define RS_1 GPIOB->ODR |= GPIO_Pin_1
 #define RW_0 GPIOB->ODR &= ~GPIO_Pin_2 // 读写选择位
 #define RW_1 GPIOB->ODR |= GPIO_Pin_2
 #define E_0 GPIOB->ODR &= ~GPIO_Pin_0 // 使能信号位
 #define E_1 GPIOB->ODR |= GPIO_Pin_0
 #define BF ((GPIOB->IDR & GPIO_Pin_15) != 0) // 忙碌标志位
 unsigned char userchar[] = {0x10, 0x06, 0x09, 0x08, 0x08, 0x09, 0x06, 0x00}; // 自定义字符℃
 extern uint32_t systick_counter; // 定时器中断中的计时变量
 // 延时n毫秒
 void delay(uint32_t nms)
 {
 systick_counter = nms;
 while (systick_counter > 0);
 }
 // 把数据端口改为读模式
 void LCDBeginRead(void)
 {
 GPIO_InitTypeDef init;
 init.GPIO_Mode = GPIO_Mode_IPU;
 init.GPIO_Pin = 0xff00;
 GPIO_Init(GPIOB, &init);
 }
 // 把数据端口改为写模式
 void LCDBeginWrite(void)
 {
 GPIO_InitTypeDef init;
 init.GPIO_Mode = GPIO_Mode_Out_PP;
 init.GPIO_Speed = GPIO_Speed_50MHz;
 init.GPIO_Pin = 0xff00;
 GPIO_Init(GPIOB, &init);
 }
 // 判断液晶模块的忙碌状态
 uint8_t LCDBusyTest(void)
 {
 uint8_t result;
 LCDBeginRead();
 RS_0;
 RW_1;
 E_1;
 __nop();
 result = BF;
 E_0;
 return result;
 }
 // 将模式设置指令或显示地址写入液晶模块
 void LCDWriteCmd(uint8_t cmd)
 {
 while (LCDBusyTest()); // 如果忙就等待
 LCDBeginWrite();
 RS_0;
 RW_0;
 E_0;
 __nop();
 __nop();
 GPIOB->ODR = (GPIOB->ODR & 0xff) + (cmd << 8);
 __nop();
 __nop();
 __nop();
 __nop();
 E_1;
 __nop();
 __nop();
 __nop();
 __nop();
 E_0;
 }
 // 设置光标位置(行, 列)
 void LCDSetPos(uint8_t row, uint8_t col)
 {
 LCDWriteCmd(0x80 + row * 0x40 + col);
 }
 // 写入字符
 void LCDWriteData(char ch)
 {
 while (LCDBusyTest());
 LCDBeginWrite();
 RS_1;
 RW_0;
 E_0;
 GPIOB->ODR = (GPIOB->ODR & 0xff) + (ch << 8);
 __nop();
 __nop();
 __nop();
 __nop();
 E_1;
 __nop();
 __nop();
 __nop();
 __nop();
 E_0;
 }
 // 写入字符串
 void LCDWriteString(char *s)
 {
 while (*s != '\0')
 {
 LCDWriteData(*s);
 s++;
 }
 }
 // 清屏, 且光标回到(0, 0)
 void LCDClear(void)
 {
 LCDWriteCmd(0x01);
 }
 // 初始化液晶
 void LCDInit(void)
 {
 uint8_t i = 3;
 delay(15); // 延时15ms,首次写指令时应给LCD一段较长的反应时间
 while (i--) // 必须写入3次
 {
 LCDWriteCmd(0x38); // 显示模式设置:16×2显示,5×7点阵,8位数据接口
 delay(5);
 }
 LCDWriteCmd(0x0c); // 显示模式设置:显示开,无光标
 delay(5);
 LCDWriteCmd(0x06); // 显示模式设置:光标右移,整屏显示不移
 delay(5);
 LCDClear();
 delay(5);
 }
 int main(void)
 {
 GPIO_InitTypeDef init;
 uint8_t i;
 
 // 初始化整个PB口
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
 init.GPIO_Mode = GPIO_Mode_Out_PP;
 init.GPIO_Pin = GPIO_Pin_All;
 init.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(GPIOB, &init);
 
 // 初始化定时器, 每1ms触发一次中断, 供delay函数使用
 SysTick_Config(SystemCoreClock / 1000);
 
 LCDInit();
 LCDSetPos(0, 1);
 LCDWriteString("Arslanbar");
 LCDSetPos(1, 2);
 LCDWriteString("Welcome");
 
 // 写入自定义字符
 LCDWriteCmd(0x40); // 设定CGRAM地址
 delay(5);
 // 第一个字符(地址0x40)
 for (i = 0; i < 8; i++)
 LCDWriteData(userchar[i]);
 // 第二个字符(地址0x48)
 for (i = 0; i < 4; i++)
 LCDWriteData(0xff);
 for (i = 0; i < 4; i++)
 LCDWriteData(0x00);
 delay(5);
 // 显示这两个字符
 LCDSetPos(0, 11);
 LCDWriteData(0x00);
 LCDWriteData(0x01);
 
 delay(3000);
 LCDClear();
 LCDWriteString("Please input the "); // 不支持自动换行...
 LCDSetPos(1, 0);
 LCDWriteString("number of rows:");
 
 while (1);
 }
 
 
 |