| 
            
            
             
              【程序】 #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); }
               
             |