

目前共有7篇帖子。
![]() |
![]() ![]() |
![]() |
注意:用串口下載程序時,需要在STM32轉接板上插上BOOT1跳線(如圖所示)。程序下載完畢後,需要拔掉跳線,否則1602液晶不能正常顯示。 |
![]() |
|
![]() |
【程序】
#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); } |
![]() |
【stm32f10x_it.c】
#include "stm32f10x_it.h" uint32_t systick_counter = 0; void BusFault_Handler(void) { while (1); } void DebugMon_Handler(void) { } void HardFault_Handler(void) { while (1); } void MemManage_Handler(void) { while (1); } void NMI_Handler(void) { } void PendSV_Handler(void) { } /*void PPP_IRQHandler(void) { }*/ void SVC_Handler(void) { } void SysTick_Handler(void) { if (systick_counter > 0) systick_counter--; } void UsageFault_Handler(void) { while (1); } |
![]() |
![]() |
![]() |
本程序只涉及到STM32 I/O口的操作以及SysTick定時器的使用。 |