網上有很多關于實現pos機中串口pos功能,學習STM32編程——具備交互功能的人機界面應用開發的知識,也有很多人為大家解答關于實現pos機中串口pos功能的問題,今天pos機之家(www.bangarufamily.com)為大家整理了關于這方面的知識,讓我們一起來看下吧!
本文目錄一覽:
實現pos機中串口pos功能
關鍵代碼:
bsp_spi.c
/*** @brief SPI2 外設初始化* @param None* @retval None*/void SPI2_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_AHB1PeriphClockCmd(SPI2_MOSI_CLK|SPI2_SCK_CLK,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE); GPIO_PinAFConfig(SPI2_MOSI_PORT,SPI2_MOSI_PINSOURCE,SPI2_MOSI_AF); GPIO_PinAFConfig(SPI2_SCK_PORT,SPI2_SCK_PINSOURCE,SPI2_SCK_AF); /* MOSI-PB15 SCK-PB10 */ GPIO_InitStructure.GPIO_Pin = SPI2_MOSI_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // 速度 50MHz GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽復用輸出 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(SPI2_MOSI_PORT,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = SPI2_SCK_PIN; GPIO_Init(SPI2_SCK_PORT,&GPIO_InitStructure); RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,ENABLE); // 復位 SPI2 RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,DISABLE); // 停止復位 SPI2 /* SPI 工作參數配置 */ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;// 雙線全雙工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // 主機模式 SPI_InitStructure.SPI_DataSize =SPI_DataSize_8b; // 數據幀長度 8bit SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; // 空閑時 SCK 高電平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;// 在 SCK 的偶數邊沿采集數據 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // 片選線由軟件管理 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;//2 分頻 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 高位在前 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC 多項式 SPI_Init(SPI2,&SPI_InitStructure); SPI_Cmd(SPI2,ENABLE);}/*** @brief SPI2 發送與接收數據* @param TxData: 要發送的數據* @retval 通過 SPI2 接收到的數據*/uint8_t SPI2_ReadWriteByte(uint8_t TxData){ uint8_t retry = 0; /* 檢查發送緩存空標志位 TXE */ while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) { retry++; if(retry>200) return 0; } SPI_I2S_SendData(SPI2, TxData); // 通過外設 SPI2 發送數據 retry=0; /* 檢查接收緩存非空標志位 RXNE */ while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) { retry++; if(retry>200) return 0; } return SPI_I2S_ReceiveData(SPI2); // 返回 SPI2 接收的數據}
oled.c
uint8_t OLED_GRAM[128][8];/*** @brief 向顯示驅動芯片寫入數據* @param data :要寫入的數據* @retval None*/void OLED_Write_Data(u8 data){ OLED_CS_LOW; OLED_DC_HIGH; //DC 引腳高電平,寫入數據 SPI2_ReadWriteByte(data); // 調用硬件 SPI 寫入 1 個字節}/*** @brief 向顯示驅動芯片寫入命令* @param Cmd :要寫入的命令* @retval None*/void OLED_Write_Cmd(u8 cmd){ OLED_CS_LOW; OLED_DC_LOW; //DC 引腳低電平,寫入命令 SPI2_ReadWriteByte(cmd); // 調用硬件 SPI 寫入 1 個字節}/*** @brief 將要顯示的數據寫入 SSD1306 的 GDDRAM* @param None* @retval None*/void OLED_Refresh_Gram(void){ uint8_t page,column; for(page=0; page<8; page++) { OLED_Write_Cmd(0xB0+page); // 設置頁地址 (0~7) OLED_Write_Cmd(0x00); // 設置列低 4 位地址 OLED_Write_Cmd(0x10); // 設置列高 4 位地址 for(column=0; column<128; column++) OLED_Write_Data(OLED_GRAM[column][page]); }}/*** @brief 初始化 OLED 控制相關 GPIO 引腳* @param None* @retval None*/void OLED_GPIO_Config(void){ GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(OLED_CS_CLK|OLED_DC_CLK|OLED_RST_CLK,ENABLE); /* CS(NSS)-PA3 | DC(Data or Command)-PA12 | RST-PA11 */ GPIO_InitStructure.GPIO_Pin = OLED_CS_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(OLED_CS_PORT,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = OLED_DC_PIN; GPIO_Init(OLED_DC_PORT,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = OLED_RST_PIN; GPIO_Init(OLED_RST_PORT,&GPIO_InitStructure);}/*** @brief OLED 顯示模塊初始化* @param None* @retval None*/void OLED_Init(void){ OLED_GPIO_Config(); // 初始化 OLED 控制相關引腳 OLED_RST_HIGH; // 硬件復位 delay_ms(100); OLED_RST_LOW; delay_ms(100); OLED_RST_HIGH; OLED_Write_Cmd(0xAE); // 關閉顯示 OLED_Write_Cmd(0x20); // 設置存儲器尋址模式 OLED_Write_Cmd(0x02); // 頁尋址模式 OLED_Write_Cmd(0xA8); // 設置行掃多路系數 OLED_Write_Cmd(0x3F); OLED_Write_Cmd(0xD3); // 設置行掃偏移 (0x00~0x3F) OLED_Write_Cmd(0x00); //not offset OLED_Write_Cmd(0x40|0x00); // 設置顯示起始行 (0x00~0x3F) OLED_Write_Cmd(0xA1); // 設置段重映射 0xa0 左右反置 0xa1 正常 OLED_Write_Cmd(0xC8); // 設置行掃方向 0xc0 上下反置 0xc8 正常 OLED_Write_Cmd(0xD9); // 設置充放電周期 OLED_Write_Cmd(0xF1); // 充電周期 15Clocks & 放電周期 1Clock OLED_Write_Cmd(0xDA); // 設置行掃方式 OLED_Write_Cmd(0x12); OLED_Write_Cmd(0x81); // 設置背光對比度 OLED_Write_Cmd(0x7F); // 默認是 0x7F(0x00~0xFF) OLED_Write_Cmd(0xA4); // 設置非全屏顯示 (0xa4/0xa5) OLED_Write_Cmd(0xA6); // 設置正常顯示 (0xa6/a7) OLED_Write_Cmd(0xD5); // 設置時鐘分頻 OLED_Write_Cmd(0x80); OLED_Write_Cmd(0x8D); // 打開內置升壓泵 OLED_Write_Cmd(0x14); //0x14 打開, 0x10 關閉 OLED_Write_Cmd(0xDB); // 反向截止電壓設置 OLED_Write_Cmd(0x40); OLED_Write_Cmd(0xAF); // 打開 OLED 面板顯示 OLED_Display_Clear(); // 清屏}/*** @brief OLED 清屏函數* @param None* @retval None*/void OLED_Display_Clear(void){ u8 i,n; for(i=0; i<8; i++) for(n=0; n<128; n++) OLED_GRAM[n][i]=0x00; OLED_Refresh_Gram(); //OLED 顯存寫入全 0}/*** @brief OLED 定位函數* @param x :列地址 (0~127) , y :行地址 (0~63)* @retval None*/void OLED_Set_Pos(u8 x,u8 y){ OLED_Write_Cmd(0xB0 + y/8); // 設置頁指針 OLED_Write_Cmd(x&0x0F); // 列低 4 位地址 OLED_Write_Cmd(((x&0xF0)>>4)|0x10); // 列高 4 位地址}/*** @brief 在指定位置畫點函數* @param x: 列地址 (0~127) , y: 行地址 (0~63)* @param mode:1 填充, 0 清空* @retval None*/void OLED_DrawPoint(u8 x,u8 y,u8 mode){ u8 page,bx,temp=0; OLED_Set_Pos(x,y); if(x>127||y>63) return; // 超出范圍 page=y/8; bx=y%8; temp=1<<bx; if(mode) OLED_GRAM[x][page]|=temp; else OLED_GRAM[x][page]&=~temp; /* 寫入顯示緩存 */ OLED_Write_Data(OLED_GRAM[x][page]);}/*** @brief 在指定位置顯示字符* @param x :列地址 (0~127) , y :行地址 (0~63)* @param chr :要顯示的字符 | size :字體大小 12/16/24* @param mode : 1 填充, 0 清空* @retval None*/void OLED_Display_Onechar(u8 x,u8 y,u8 chr,u8 size,u8 mode){ u8 temp,t,t1; u8 y0=y; u8 csize=(size/8+((size%8)?1:0))*(size/2); chr=chr-' '; // 得到偏移后的值 for(t=0; t<csize; t++) { if(size==12) temp = oled_asc2_1206[chr][t]; // 調用 1206 字體 else if(size==16) temp = oled_asc2_1608[chr][t]; // 調用 1608 字體 else if(size==24) temp = oled_asc2_2412[chr][t]; // 調用 2412 字體 else return; // 字庫中不存在相關字體 for(t1=0; t1<8; t1++) { if(temp & 0x80) OLED_DrawPoint(x, y, mode); else OLED_DrawPoint(x, y, !mode); temp <<= 1; y++; if((y-y0) == size) { y = y0; x++; break; } } }}/*** @brief 在指定位置顯示字符串* @param x :列地址 (0~127) , y :行地址 (0~63)* @param *p :要顯示的字符串起始地址* @param size :字體大小 12/16/24* @retval None*/void OLED_Display_String(u8 x,u8 y,char *p, u8 size){ while((*p <= '~') && (*p >= ' '))// 判斷是否為非法字符 { if(x > (128-(size/2))) { x = 0; y += size; } if(y > (64-size)) { y = x = 0; OLED_Display_Clear(); } OLED_Display_Onechar(x,y,*p,size,1); x += size/2; p++; }}
bsp_rtc.c
/*** @brief 顯示日期和時間* @param None* @retval None*/void RTC_Show_DateTime(void){ char WeekDay[4]; // 用于存放星期的縮寫,如 Mon RTC_TimeTypeDef RTC_TimeStructure; RTC_DateTypeDef RTC_DateStructure; /* 獲取日歷 */ RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure); RTC_GetDate(RTC_Format_BIN, &RTC_DateStructure); /* 將 RTC 獲取到的“星期”參數轉化為相應的英文縮寫 */ switch(RTC_DateStructure.RTC_WeekDay) { case 1: // 星期一 WeekDay[0]='M';WeekDay[1]='O';WeekDay[2]='N'; break; case 2: // 星期二 WeekDay[0]='T';WeekDay[1]='U';WeekDay[2]='E'; break; case 3: // 星期三 WeekDay[0]='W';WeekDay[1]='E';WeekDay[2]='D'; break; case 4: // 星期四 WeekDay[0]='T';WeekDay[1]='H';WeekDay[2]='U'; break; case 5: // 星期五 WeekDay[0]='F';WeekDay[1]='R';WeekDay[2]='I'; break; case 6: // 星期六 WeekDay[0]='S';WeekDay[1]='A';WeekDay[2]='T'; break; case 7: // 星期日 WeekDay[0]='S';WeekDay[1]='U';WeekDay[2]='N'; break; } /* 串口顯示日期 */ printf("The Date : Y:20%0.2d - M:%0.2d - D:%0.2d - W:%0.2d\\", RTC_DateStructure.RTC_Year, RTC_DateStructure.RTC_Month, RTC_DateStructure.RTC_Date, RTC_DateStructure.RTC_WeekDay); /* 使用 OLED 顯示日期 */ sprintf(DateShow,"20%0.2d-%0.2d-%0.2d %s", RTC_DateStructure.RTC_Year, RTC_DateStructure.RTC_Month, RTC_DateStructure.RTC_Date, WeekDay); /* 串口顯示時間 */ printf("The Time : %0.2d:%0.2d:%0.2d \\\\", RTC_TimeStructure.RTC_Hours, RTC_TimeStructure.RTC_Minutes, RTC_TimeStructure.RTC_Seconds); /* 使用 OLED 顯示時間 */ sprintf(TimeShow,"%0.2d:%0.2d:%0.2d", RTC_TimeStructure.RTC_Hours, RTC_TimeStructure.RTC_Minutes, RTC_TimeStructure.RTC_Seconds); OLED_Show_DateTime(); // 使用 OLED 顯示日期時間}/*** @brief OLED 顯示日期和時間* @param None* @retval None*/void OLED_Show_DateTime(void){ OLED_Display_String(32,0,"Calendar",16); OLED_Display_String(4,32,DateShow,16); OLED_Display_String(32,48,TimeShow,16);}
main.c
int main(void){ delay_init(168); // 延時函數初始化 LED_Init(); //LED 端口初始化 Key_Init(); // 按鍵端口初始化 EXTIx_Init(); // 外部中斷初始化 USART1_Init(115200); //USART1 初始化 IIC_Init(); //IIC 總線初始化 BH1750_Init(); //BH1750 初始化 DHT11_Init(); //DHT11 初始化 SPI2_Init(); //SPI2 外設初始化 OLED_Init(); //OLED 顯示模塊初始化 RTC_CLK_Config(1); //RTC 配置,時鐘源選擇 LSE while(DHT11_Init()) //DHT11 初始化 { printf("DHT11 Init Error!\\"); delay_ms(500); } printf("DHT11 Init Success!\\"); /* 若備份區域讀取的值不對 */ if (RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x5F5F) { RTC_Set_DateTime(); // 設置時間和日期 } else { printf("\\ 不需要重新配置 RTC …… \\"); /* 使能 PWR 時鐘 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); /* PWR_CR:DBF 置 1 ,使能 RTC 、 RTC 備份寄存器和備份 SRAM 的訪問 */ PWR_BackupAccessCmd(ENABLE); /* 等待 RTC APB 寄存器同步 */ RTC_WaitForSynchro(); } while(1) { if(keyValue == KEY_D_PRESS) // 如果“下鍵”按下 { if(refresh_flag == 1) { refresh_flag = 2; OLED_Display_Clear(); // 刷一次屏 } RTC_Show_DateTime(); // 顯示時間和日期 } else // 如果“下鍵”沒有按下 { bh1750Light = BH1750_Measure(); // 讀取 BH1750 的光照強度值 DHT11_Read_Data(&temperature,&humidity);// 讀取 DHT11 的溫濕度值 /* 組合需要顯示的信息 */ sprintf(lightString,"Light:%0.5d",bh1750Light); printf("%s",lightString); sprintf(tempString,"Temp:%d",temperature); printf("%s",tempString); sprintf(humiString,"Humi:%d",humidity); printf("%s",humiString); if(refresh_flag == 2) { refresh_flag = 1; OLED_Display_Clear(); // 刷一次屏 } Show_TempHumiLight(); // 顯示環境參數 } LED1 = ~LED1; delay_ms(500); }}/*** @brief OLED 顯示環境參數 ( 溫度 / 濕度 / 光照強度 )* @param None* @retval None*/void Show_TempHumiLight(void){ OLED_Display_String(20,0,"Environment",16); OLED_Display_String(20,16,tempString,16); OLED_Display_String(20,32,humiString,16); OLED_Display_String(20,48,lightString,16);}
以上就是關于實現pos機中串口pos功能,學習STM32編程——具備交互功能的人機界面應用開發的知識,后面我們會繼續為大家整理關于實現pos機中串口pos功能的知識,希望能夠幫助到大家!
