stm32-12864并行驅(qū)動程序.doc
《stm32-12864并行驅(qū)動程序.doc》由會員分享,可在線閱讀,更多相關(guān)《stm32-12864并行驅(qū)動程序.doc(16頁珍藏版)》請在裝配圖網(wǎng)上搜索。
//////////////////////////////////////////////////////////////////////////////// //stm32-12864并行驅(qū)動程序 //////////////////////////////////////////////////// #include "delay.h" //必須配合 delay.c 和 delay.h 文件使用,所以要包含 delay.h。 #include "display12864.h" f /********** 以下是相關(guān)引腳定義。**************/ // A 口的 #define DisIO GPIOE //定義 12864 要使用的 I/O 端口。 #define DisClk RCC_APB2Periph_GPIOE //定義 12864 要使用的 I/O 端口 的時鐘。 #define Data GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPI O_Pin_7 //定義 12864 使用的數(shù)據(jù)引腳。 #define EN GPIO_Pin_10 //定義使能端使用的引腳 /*********************************************/ #define DisIOIO GPIOE //定義 12864 要使用的 I/O 端口。 #define DisClkIO RCC_APB2Periph_GPIOE //定義 12864 要使用的 I/O 端口 的時鐘。 #define RS #define RW GPIO_Pin_9 GPIO_Pin_8 /*光標(biāo)定位函數(shù)定義結(jié)束。*/ #define x1 0x80 #define x2 0x88 #define y 0x80 GPIO_InitTypeDef GPIOStru; //定義用于定義所以引腳為輸出的變量。 /****************************************************************************** * * 函數(shù)名 : IOInitOut * 函數(shù)描述 : 把所有端口初始化為推挽輸出模式的函數(shù) * 輸入?yún)?shù) : 無 * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void IOInitOut(void) { //IO 組 GPIOStru.GPIO_Mode = GPIO_Mode_Out_PP; // 定 義 所 有 的 引 腳 為 推挽輸出的變量初始化。 GPIOStru.GPIO_Speed = GPIO_Speed_50MHz; GPIOStru.GPIO_Pin = Data | EN; RCC_APB2PeriphClockCmd(DisClkIO,ENABLE); GPIO_Init(DisIO,&GPIOStru); //IO 組 GPIOStru.GPIO_Mode = GPIO_Mode_Out_PP; // 定 義 所 有 的 引 腳 為 推挽輸出的變量初始化。 GPIOStru.GPIO_Speed = GPIO_Speed_50MHz; GPIOStru.GPIO_Pin = RS|RW; RCC_APB2PeriphClockCmd(DisClkIO,ENABLE); GPIO_Init(DisIO,&GPIOStru); } /****************************************************************************** * * 函數(shù)名 : IOInitIn * 函數(shù)描述 : 把數(shù)據(jù)引腳初始化為浮空輸入的函 * 輸入?yún)?shù) : 無 * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void IOInitIn(void) { GPIOStru.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 定義數(shù)據(jù) 引腳為浮空輸 入的變量初始化。 GPIOStru.GPIO_Speed = GPIO_Speed_50MHz; GPIOStru.GPIO_Pin = Data; RCC_APB2PeriphClockCmd(DisClkIO,ENABLE); // 把 所 有 端 口 初 始 化 為輸出模式的函數(shù)。 GPIO_Init(DisIO,&GPIOStru); } /****************************************************************************** * * 函數(shù)名 : WaitBusy * 函數(shù)描述 : 等待 12864 的忙狀態(tài)結(jié)束的函數(shù) * 輸入?yún)?shù) : 無 * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void WaitBusy(void) { IOInitIn(); // 把 數(shù) 據(jù)引腳定義為浮空輸入 GPIO_ResetBits(DisIOIO,RS); //RS = 0 GPIO_SetBits(DisIOIO,RW); //RW = 1. GPIO_SetBits(DisIO,EN); //EN = 1. while(GPIO_ReadInputData(DisIO) & 0x0080); //只要位 7 的值,位 7 是忙標(biāo)志位 GPIO_ResetBits(DisIO,EN); //EN = 0; IOInitOut(); //把所有引腳定義為輸出。 } /****************************************************************************** * * 函數(shù)名 : WriteCmd * 函數(shù)描述 : 寫命令函數(shù) * 輸入?yún)?shù) : 8 位命令 * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void WriteCmd(uint8_t cmd) { WaitBusy(); GPIO_ResetBits(DisIOIO,RS); //RS = 0. GPIO_ResetBits(DisIOIO,RW); //RW = 0. GPIO_SetBits(DisIO,EN); //EN = 1. DisIO->ODR=((DisIO->ODR & 0xff00)|cmd); //此處,只有直接操作寄存器才能 //達(dá)到,只改變輸出數(shù)據(jù)寄存器 ODR 的低 8 位,其它位 //不變的目的。因為,只有低 8 位是數(shù)據(jù)引腳, //其它位可能是控制引腳,不能改變。 delay_us(2); GPIO_ResetBits(DisIO,EN); //EN = 0; delay_us(2); } /****************************************************************************** * * 函數(shù)名 : WriteData * 函數(shù)描述 : 寫數(shù)據(jù)函數(shù) * 輸入?yún)?shù) : 8 位命令 * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void WriteData(uint8_t data) { WaitBusy(); GPIO_SetBits(DisIOIO,RS); //RS = 1. GPIO_ResetBits(DisIOIO,RW); //RW = 0. GPIO_SetBits(DisIO,EN); //EN = 1. DisIO->ODR=((DisIO->ODR & 0xff00)|data); //同上。 delay_us(2); GPIO_ResetBits(DisIO,EN); //EN = 0; delay_us(2); } /****************************************************************************** * * 函數(shù)名 : ReadData * 函數(shù)描述 : 讀 IO 口狀態(tài) * 輸入?yún)?shù) : 無 * 輸出結(jié)果 : 無 * 返回值 : 8 位數(shù)據(jù) ******************************************************************************* / uint8_t ReadData(void) { uint8_t uc_Content; WaitBusy(); IOInitIn(); delay_ms(10); //注意:用 BCDE 組 IO 口必須這個延時! GPIO_SetBits(DisIOIO,RW); //RW = 1; 讀模式 GPIO_SetBits(DisIOIO,RS); //RS = 1; 數(shù)據(jù) GPIO_SetBits(DisIO,EN); //EN = 1. 使能 delay_us(2); //延時很重要 // uc_Content = (DisIO->IDR)&0x00ff; uc_Content = GPIO_ReadInputData(DisIO); GPIO_ResetBits(DisIO,EN); //EN = 0. delay_us(2); //延時很重要 IOInitOut(); return uc_Content; } /****************************************************************************** * * 函數(shù)名 : InitDis * 函數(shù)描述 : 初始化 12864 和要用到的 STM 32 的引腳 * 輸入?yún)?shù) : 無 * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void InitDis(void) { IOInitOut(); delay_init(8); //初始化延時函數(shù)的微妙計數(shù)基數(shù)。 WriteCmd(0x30); //選擇基本指令集,和,8 位數(shù)據(jù)模式。 delay_ms(2); WriteCmd(0x0c); //開顯示,無游標(biāo),不反白. delay_ms(2); WriteCmd(0x01); //清除顯示,并將 DDRAM 的地址計數(shù)器 AC 設(shè)為 00H. delay_ms(2); WriteCmd(0x06); //設(shè)置,外部讀寫數(shù)據(jù)后,地址記數(shù)器 AC 會自動加 1。 delay_ms(2); WriteCmd(0x80); //將 DDRAM 地址計數(shù)器 AC 設(shè)為 0. delay_ms(2); } /****************************************************************************** * * 函數(shù)名 : DisStr * 函數(shù)描述 : 顯示字符串的函數(shù) * 輸入?yún)?shù) : 字符串地址 * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void DisStr(uint8_t *s) { while(*s != \0) { WriteData(*s); s++; delay_ms(2); } } /****************************************************************************** * * 函數(shù)名 : DisInt * 函數(shù)描述 : 顯示整型變量的函數(shù),最多顯示 16 位的整數(shù)(只能顯示正數(shù)) * 輸入?yún)?shù) : 16 位二進(jìn)制無符號整型數(shù)據(jù) * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void DisInt(uint16_t num) { 數(shù)倍, uint8_t temp[17]; uint8_t str[17]; int i=0,j=0; while(num != 0) //這里不能用 num%10 != 0,如果 num 是 10 的整 //例如,100,這樣就會出 錯,根本就不能進(jìn)入循環(huán)體。 { temp[i] = (num%10) + 0x30; num /= 10; i++; } i--; //因為 i 在退出循環(huán)之前還自加了一次,此時, // 指向最后一個存儲有用 值的元素的后一個位置。 while(i != -1) //因為 i=0 時,temp[0]還是有用值。 { str[j] = temp[i]; j++; i--; } str[j] = \0; //因為 i 在退出循環(huán)之前還自加了一次,此時, // 指向最后一個存儲有用 值的元素的后一個位置。 DisStr(str); } /****************************************************************************** * * 函數(shù)名 : DisFloat * 函數(shù)描述 : 顯示有 n 位小數(shù)的浮點(diǎn)數(shù),總位數(shù)不超過 16 位 * 輸入?yún)?shù) : 16 位數(shù)據(jù) * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void DisFloat(int n,float fnum) { long int num = fnum*10; uint8_t temp[17]; uint8_t str[17]; int i=0,j=0; while(num != 0) { temp[i] = (num%10)+0x30; num/=10; i++; if(i == n) //4 位小數(shù)處理完后,加入小數(shù)點(diǎn)。 { } } i--; temp[i] = .; i++; while(i != -1) { str[j] = temp[i]; j++; i--; } str[j]=\0; DisStr(str); } /****************************************************************************** * * 函數(shù)名 : Locate16 * 函數(shù)描述 : 光標(biāo)定位函數(shù), 第一個參數(shù)為行坐標(biāo), 第二個為列坐標(biāo), 起始坐標(biāo)是 1 行 1 列, 只能以 16 個點(diǎn)的寬度為單位移 動 * 輸入?yún)?shù) : row ---- 行, col ---- 列 * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void Locate16(int row, int col) { switch(row) { case 1: WriteCmd(0x80+col-1); break; case 2: WriteCmd(0x90+col-1); break; case 3: WriteCmd(0x88+col-1); break; case 4: WriteCmd(0x98+col-1); break; } } //顯示繪圖 全屏 /****************************************************************************** * * 函數(shù)名 : DisInt * 函數(shù)描述 : 顯示有 1 位小數(shù)的浮點(diǎn)數(shù),總位數(shù)不超過 16 位 * 輸入?yún)?shù) : 數(shù)據(jù) * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void ImageWhole(uint8_t *img) { uint8_t i,j; for(j=0;j<32;j++) //上半屏 { for(i=0;i<8;i++) { WriteCmd(0x34); WriteCmd(y+j); //給命令給第幾行 垂直坐標(biāo) WriteCmd(x1+i); //給命令給第幾列 水平坐標(biāo) WriteCmd(0x30); WriteData(img[j*16+i*2]); WriteData(img[j*16+i*2+1]); } } for(j=32;j<64;j++) //下半屏 { for(i=0;i<8;i++) { WriteCmd(0x34); //關(guān)閉繪圖 WriteCmd(y+j-32); //給命令給第幾行 垂直坐標(biāo) WriteCmd(x2+i); //給命令給第幾列 水平坐標(biāo) WriteCmd(0x30); WriteData(img[j*16+i*2]); WriteData(img[j*16+i*2+1]); } } WriteCmd(0x36); //打開繪圖 } /****************************************************************************** * * 函數(shù)名 : DrawPoint * 函數(shù)描述 : 畫點(diǎn)函數(shù) * 輸入?yún)?shù) : xx ---- 行, yy ---- 列 (x, y) * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void DrawPoint(uint8_t xx,uint8_t yy) { uint8_t x_byte, x_bit; //在橫坐標(biāo)的哪一個字節(jié),哪一個位 uint8_t y_byte, y_bit; uint8_t tmph, tmpl; //定義兩個臨時變量,用于存放讀出來的數(shù)據(jù) tmph=0; tmpl=0; xx = xx & 0x7F; yy = yy & 0x3F; x_byte = xx / 16; //算出它在哪一個字節(jié)(地址) 注意一個地址是 16 位的 x_bit = xx & 0x0F; //算出它在哪一個位 y_byte = yy /32; //y 是沒在哪個字節(jié)這個說法 這里只是確定它在上半屏還是下半屏 上半屏 1:下半屏 y_bit = yy & 0x1F; //y_bit 確定它是在第幾行 WriteCmd(0x34); //擴(kuò)展指令集 WriteCmd(0x34); //繪圖顯示關(guān)閉 WriteCmd(0x80 + y_bit); //先寫垂直地址(最高位必須為 1) 具體參照數(shù)據(jù)手冊 WriteCmd(0x80 + x_byte + 8*y_byte); //水平坐標(biāo) //下半屏的水平坐標(biāo)起始地址為 0x88 //(+8*y_byte)就是用來確定 在上半屏還是下半屏 ReadData(); //先空讀一次 tmph = ReadData(); //讀高位 tmpl = ReadData(); //讀低位 WriteCmd(0x80 + y_bit); //讀操作會改變 AC,所以重新設(shè)置一次 WriteCmd(0x80 + x_byte + 8*y_byte); // // //0: // if (x_bit < 8) //如果 x_bit 位數(shù)小于 8 { WriteData(tmph|(0x01 << (7 - x_bit))); //寫高字節(jié)。因為坐標(biāo)是從左向右的 //而 GDRAM 高位在左,底位在右 WriteData(tmpl); //原數(shù)據(jù)送回 } else { WriteData(tmph); //原數(shù)據(jù)送回 WriteData(tmpl | (0x01 << (15 - x_bit))); } WriteCmd(0x36); //打開繪圖顯示 WriteCmd(0x30); //回到基本指令集,畢竟 ST7920 是以字符為主的 } /****************************************************************************** * * 函數(shù)名 : ClearPoint * 函數(shù)描述 : 清除點(diǎn)函數(shù) * 輸入?yún)?shù) : xx ---- 行, yy ---- 列 (x, y) * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void ClearPoint(uint8_t xx,uint8_t yy) { uint8_t x_byte, x_bit; //在橫坐標(biāo)的哪一個字節(jié),哪一個位 uint8_t y_byte, y_bit; uint8_t tmph, tmpl; //定義兩個臨時變量,用于存放讀出來的數(shù)據(jù) tmph=0; tmpl=0; xx = xx & 0x7F; yy = yy & 0x3F; x_byte = xx / 16; //算出它在哪一個字節(jié)(地址) 注意一個地址是 16 位的 x_bit = xx & 0x0F; //算出它在哪一個位 y_byte = yy /32; //y 是沒在哪個字節(jié)這個說法 這里只是確定它在上半屏還是下半屏 上半屏 1:下半屏 // // //0: y_bit = yy & 0x1F; //y_bit 確定它是在第幾行 WriteCmd(0x34); //擴(kuò)展指令集 WriteCmd(0x34); //繪圖顯示關(guān)閉 WriteCmd(0x80 + y_bit); //先寫垂直地址(最高位必須為 1) // 具體參照數(shù)據(jù)手冊 WriteCmd(0x80 + x_byte + 8*y_byte); //水平坐標(biāo) //下半屏的水平坐標(biāo)起始地址為 0x88 //(+8*y_byte)就是用來確定 在上半屏還是下半屏 ReadData(); //先空讀一次 tmph = ReadData(); //讀高位 tmpl = ReadData(); //讀低位 WriteCmd(0x80 + y_bit); //讀操作會改變 AC,所以重新設(shè)置一次 WriteCmd(0x80 + x_byte + 8*y_byte); if (x_bit < 8) //如果 x_bit 位數(shù)小于 8 { WriteData(tmph&(0xfe << (7 - x_bit))); //寫高字節(jié)。因為坐標(biāo)是從 左向右的 右 //而 GDRAM 高位在左,底位在 WriteData(tmpl); // 原 數(shù) 據(jù)送回 } else { } WriteData(tmph); //原數(shù)據(jù)送回 WriteData(tmpl & (0xfe << (15 - x_bit))); WriteCmd(0x36); //打開繪圖顯示 WriteCmd(0x30); //回到基本指令集,畢竟 ST7920 是以字符為主的 } /****************************************************************************** * * 函數(shù)名 : ClearAll * 函數(shù)描述 : 清整個 GDRAM 空間 * 輸入?yún)?shù) : 無 * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void ClearAll(void) { uint8_t xxx, yyy; for(yyy=0; yyy<64; yyy++) { for(xxx=0; xxx<16; xxx++) { WriteCmd(0x34); WriteCmd(yyy+0x80); //行地址 WriteCmd(xxx+0x80); //列地址 WriteCmd(0x30); WriteData(0x00); WriteData(0x00); } } } /****************************************************************************** * * 函數(shù)名 : DrawLineX * 函數(shù)描述 : 畫水平線 * 輸入?yún)?shù) : xx0 ---- X 起始, xx1 ---- X 結(jié)束, yy ---- Y * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void DrawLineX(uint8_t xx0,uint8_t xx1,uint8_t yy) { uint8_t temp; if(xx0 > xx1) { temp = xx0; xx0 = xx1; xx1 = temp; } for(xx0=xx0; xx0<=xx1; xx0++) { DrawPoint(xx0, yy); } } /****************************************************************************** * * 函數(shù)名 : DrawLineY * 函數(shù)描述 : 畫垂直線 * 輸入?yún)?shù) : yy0 ---- Y 起始, yy1 ---- Y 結(jié)束, xx X * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void DrawLineY(uint8_t xx, uint8_t yy0, uint8_t yy1) { uint8_t temp; if(yy0>yy1) { temp=yy0; yy0=yy1; yy1=temp; } for(yy0=yy0;yy0<=yy1;yy0++) { DrawPoint(xx,yy0); } } /****************************************************************************** * * 函數(shù)名 : DrawLine * 函數(shù)描述 : 畫直線 * 輸入?yún)?shù) : xx1 ---- X 起始, yy1 ---- Y 起始, xx2 ---- X 結(jié)束, yy2 ---- Y 結(jié)束, x:橫坐標(biāo)值,范圍 0~127 y:縱坐標(biāo)值,范圍 0~63 xx2>=xx1 * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void DrawLine(uint8_t xx1,uint8_t yy1,uint8_t xx2,uint8_t yy2) { uint8_t x_add,y_add,y_temp,Line_K; xx1&=0x7f; xx2&=0x7f; //去掉 128 倍 yy1&=0x3f; yy2&=0x3f; //去掉 64 倍 if(xx2>xx1) { if( yy2>yy1 || yy2==yy1 ) { Line_K=(yy2-yy1)/(xx2-xx1); for(x_add=0;x_add<=(xx2-xx1);x_add++) { y_temp=yy1+(Line_K*(x_add+xx1)); DrawPoint(x_add+xx1,y_temp); } } else { Line_K=(yy1-yy2)/(xx2-xx1); for(x_add=0;x_add<=(xx2-xx1);x_add++) { y_temp=yy1-(Line_K*(x_add+xx1)); DrawPoint(x_add+x1,y_temp); } } } else if(xx2==xx1) { for(y_add=0;y_add<=(yy2-yy1);y_add++) { DrawPoint(xx1,yy1+y_add); } } } /****************************************************************************** * * 函數(shù)名 : DrawCircle * 函數(shù)描述 : 畫圓函數(shù) * 輸入?yún)?shù) : x0, y0 為圓心坐標(biāo), r 為圓的半徑 * 輸出結(jié)果 : 無 * 返回值 : 無 ******************************************************************************* / void DrawCircle(uint8_t x0 , uint8_t y0 , uint8_t r) { int8_t a, b; int8_t di; if( r > 31 || r == 0 ) //圓大于液晶屏或者沒半徑則返回 return; a = 0; b = r; di = 3 - 2 * r;//判斷下個點(diǎn)位置的標(biāo)志 while(a <= b) { DrawPoint( x0 - b , y0 - a); //3 DrawPoint( x0 + b , y0 - a); //0 DrawPoint( x0 - a , y0 + b); //1 DrawPoint( x0 - b , y0 - a); //7 DrawPoint( x0 - a , y0 - b); //2 DrawPoint( x0 + b , y0 + a); //4 DrawPoint( x0 + a , y0 - b); //5 DrawPoint( x0 + a , y0 + b); //6 DrawPoint( x0 - b , y0 + a); a ++; //使用 bresenham 算法畫圓 if(di < 0) di += 4 * a + 6; else { } di += 10 + 4 * (a - b); b --; DrawPoint( x0 + a , y0 + b); } }- 1.請仔細(xì)閱讀文檔,確保文檔完整性,對于不預(yù)覽、不比對內(nèi)容而直接下載帶來的問題本站不予受理。
- 2.下載的文檔,不會出現(xiàn)我們的網(wǎng)址水印。
- 3、該文檔所得收入(下載+內(nèi)容+預(yù)覽)歸上傳者、原創(chuàng)作者;如果您是本文檔原作者,請點(diǎn)此認(rèn)領(lǐng)!既往收益都?xì)w您。
下載文檔到電腦,查找使用更方便
9.9 積分
下載 |
- 配套講稿:
如PPT文件的首頁顯示word圖標(biāo),表示該P(yáng)PT已包含配套word講稿。雙擊word圖標(biāo)可打開word文檔。
- 特殊限制:
部分文檔作品中含有的國旗、國徽等圖片,僅作為作品整體效果示例展示,禁止商用。設(shè)計者僅對作品中獨(dú)創(chuàng)性部分享有著作權(quán)。
- 關(guān) 鍵 詞:
- stm32 12864 并行 驅(qū)動程序
鏈接地址:http://m.hcyjhs8.com/p-6624364.html