制作出來的DIY書寫屏幕實物圖如下:
IMG20180526170124.jpg (2.6 MB, 下載次數: 86)
下載附件
光筆書寫
2018-9-2 21:16 上傳
IMG20180526165951.jpg (2.88 MB, 下載次數: 86)
下載附件
逐點掃描書寫屏幕
2018-9-2 21:16 上傳
IMG20180526170033.jpg (2.87 MB, 下載次數: 74)
下載附件
寫好的字在一般顯示屏上顯示
2018-9-2 21:16 上傳
單片機源程序如下:
- #include "dianzhen3_lib.h"
- #define u8 unsigned char
- #define dianzhen_138_location P2
- bit scan_f = 0;//當輸入按鍵按下時138點陣開始掃描
- bit odd_or_even = 0;//修改鍵按下次數的奇偶標志位
- bit input_or_finish_flag = 0;
- u8 k=0;
- u8 key_value;
- u8 location_num = 0;
- u8 del_location_num = 0;
- u8 xdata t_collect[130]={0xff};
- u8 xdata t_del[30]={ 0xff };
- u8 xdata t_ku[254];
- u8 code t_ku_1[254]={ //0xff被保留,用作采集數據的最后一個.0xfe也被保留,t_ku[]填充
- 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
- …………
- …………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
- 0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd};
- extern unsigned char code infro3[208]; //淮工光信秦帥
- void main()
- {
- u8 i, j;
-
- P3M0 = 0; //使P3口與P2口為準雙向口,和傳統51單片機一樣
- P3M1 = 0;
- P2M0 = 0xff; //P2口為推挽輸出用來驅動138點陣
- P2M1 = 0;
- P1M0 = 0xff; //用P1口來驅動595點陣屏
- P1M1 = 0;
- P0M0 = 0x07;
- P0M1 = 0;//使P00.P01.P02推挽輸出
- EA = 1;//按鍵中斷一直開
- EX1 = 1;
- IT1 = 1;
- P55 = 1; //因為手頭上的這塊15單片機的P3.5口始終為0,不知為啥,就用了P55來替代,用作按鍵部分
- P3 = 0xff;
- P01 = 0; ////綠燈,高電平點亮
- P00 = 0; //紅燈,高電平點亮
- P02 = 1; //138點陣使能端,低電平有效
-
- for(i=0; i<254; i++ ) //賦值t_ku[]
- {
- t_ku[i] = t_ku_1[i];
- }
- while(scan_f == 0) //當沒開始按下的時候一直顯示“淮工光信秦帥”
- {
- infro_display( 3 );
- }
- while(1)
- {
- while( scan_f == 1 )
- {
- if( odd_or_even == 0 ) //只有當修改鍵是偶數次按下的時候才掃描(偶數次包含0次)
- {
- for(k=0; k<254; k++) //開始掃描138點陣
- {
- dianzhen_138_location = t_ku[k];
- Delay(1) ;
- }
- }
- else if( odd_or_even == 1 ) //修改鍵奇數次按下時,將收集到的數據顯示出來
- {
- for( i=0; t_collect[i]!=0xff ; i++ )
- {
- if( t_collect[i] == 0xfe )
- {
- continue;
- }
- dianzhen_138_location = t_collect[i];
- Delay(2);
- }
- }
-
- if( key_value == input )
- {
- key_value = 0 ; //將key_value內容清空
- location_num = 0;
- del_location_num = 0;
- odd_or_even = 0;
- for(i=0; i<254; i++ ) //賦值t_ku[]
- {
- t_ku[i] = t_ku_1[i];
- }
-
- t_collect[0] = 0xff;
- t_del[0] = 0xff;
-
- EX0 = 1; //啟動外部中斷0(光筆生效)
- IT0 = 1;
- }
-
- if( key_value == modify)
- {
- key_value = 0;
- if( t_collect[0] != 0xff )//沒有采集數據則不修改
- {
- odd_or_even = ~odd_or_even;//為1時是奇數次按下,為0時是偶數次按下
- if( odd_or_even == 0 )//如果修改是偶數次按下修改鍵,則收回被刪除的點
- {
- if( t_del[0] != 0xff )
- {
- for( i=0; t_del[i] != 0xff ; i++ )
- {
- for(j=0;t_ku[j] != 0xfe ; j++);
- t_ku[j] = t_del[i];
- }
- t_del[0] = 0xff; //數組的第一個數若為0xff,則說明此數組里面無需執行數據
- del_location_num = 0;
- }
- }
-
- }
- }
-
-
- if( key_value == save )
- {
- key_value = 0;
- EA = 0;
- if (t_collect[ 0 ] == 0xff)//若沒有需要保存的數據,則閃一下紅燈;返回
- {
- P01 = 1;//如果保存失敗則紅燈閃爍一下(P01口接紅燈)高電平點亮
- Delay(255);
- Delay(255);
- Delay(255);
- Delay(255);
- Delay(255);
- Delay(255);
- P01 = 0;
- }
- else
- {
- if ( save_data( t_collect ) !=0 )
- {
- P00 = 1;//如果保存成功則綠燈閃爍一下(P01口接綠燈)高電平點亮
- Delay(255);
- Delay(255);
- Delay(255);
- Delay(255);
- Delay(255);
- Delay(255);
- P00 = 0;
- key_value = input;//若保存成功則開始下個字的輸入,若不成功則返回
- }
- else
- {
- P01 = 1;//如果沒有保存成功則紅燈閃爍一下(P11口接紅燈)
- Delay(255);
- Delay(255);
- Delay(255);
- Delay(255);
- Delay(255);
- Delay(255);
- P01 = 0;
- }
-
- }
- EA = 1;
- }
-
- }
- if( key_value == finish )
- {
- key_value = 0;
- EX0 = 0; //關閉外部中斷0(光筆生效)
- P02 = 1; //關閉書寫屏(P02)為138點陣屏的使能端
- // IT0 = 1;
- P17 = 1;//595點陣屏的使能端,低電平有效(即為高電平是全部輸出低電平)
- }
-
- if( key_value == display )
- {
- key_value = 0;
-
- EX0 = 0;
- P02 = 1; //關閉書寫屏(P02)為138點陣屏的使能端
- data_display(); //一直顯示直到input或者finish按鍵按下
- // for(k=0; k<254; k++) //用t_ku數組來存顯示數據,返回后需重新賦值
- // {
- // dianzhen_138_location = t_ku[k];
- // Delay(1) ;
- // }
- // EX0 = 1;
- }
- }
-
- }
- void key_interput1() interrupt 2
- {
- u8 t;
- t = P3;
- Delay10ms() ;
- if( t != P3 )
- {
- return ;
- }
-
- switch( t & 0Xd0 )
- {
- case 0xc0: key_value = input ; scan_f = 1 ; input_or_finish_flag = 1; P02 =0;break;//P02是138點陣的使能端口
- case 0x90: key_value = save ; input_or_finish_flag = 0; break;
- case 0x50: key_value = finish ; scan_f = 0 ; input_or_finish_flag = 1; break;
- case 0xd0: if( P55 == 0 ) {key_value = modify ;input_or_finish_flag = 0;}
- else if( P33 == 0 ){key_value = display ; scan_f = 0 ;input_or_finish_flag = 0;} break;
- }
-
- for(t=0; t<50; t++)
- {
- while(P33 == 0)
- {
- Delay10ms();
- }
- }
- }
- void Led_3du33_interrput() interrupt 0
- {
- u8 i ;
- //static del_f = 1;
- EX0=0;
- for(i=0; i<location_num; i++) //判斷此點是否已經采集過若采集過則不再重新采集
- {
- if( ( t_collect[i] == dianzhen_138_location ) && (dianzhen_138_location != 0xfe))
- {
- if( (odd_or_even == 1) && ( del_location_num<28))//修改鍵奇數次按下,這里允許刪除了28個點坐標,可以改動
- {
- //Delay10ms() ; //如果真要刪除點的話,在這里用一下延時,慢一點
- //if (P32 == 0)
- //{
- // del_f=~del_f;
- //if(del_f == 1)
- //{
- if( t_collect[i-1] == dianzhen_138_location ) //這個if是用來防止滯后響應的
- { //比如因為上一個點響應的中斷
- t_del[del_location_num++] = t_collect[(i-1)] ;//但是點陣坐標已經跑到下一個了
- t_collect[(i-1)]=0xfe; //消除的數據點需要用0xfe來填充,0xfe將會在存儲數據時被消除
- }
- else
- {
- t_del[del_location_num++] = t_collect[i] ;
- t_collect[i]=0xfe; //消除的數據點需要用0xfe來填充,0xfe將會在存儲數據時被消除
- }
- t_del[del_location_num] = 0xff ;//用0xff表示結束
- //}
- //}
- }
- EX0 = 1;
- return;
- }
-
- }
- if( location_num <130 )
- {
- t_collect[ location_num++] = dianzhen_138_location;//t_ku[]掃描時選中一個數,則消失一個點
- if(t_ku[(k-1)] == dianzhen_138_location) // 這個if的作用和刪除點時的if目的是一樣的
- {
- t_ku[(--k)] = 0xfe;//被選中的數,用0xfe來替補 (因為有時候時間有點錯開了,比如掃描函數已經執行完了K++,然后才跑到中斷的情況)
- }
- else
- {
- t_ku[k] = 0xfe;//被選中的數,用0xfe來替補 (0xfe將會在保存的時候被刪除)
- }
- t_collect[ location_num] = 0xff ;//0xff 始終為最后一個數
- }
- EX0 = 1;
- return;
- }
復制代碼- #include "intrins.h"
- #include <stc15.h>
- #define ENABLE_IAP 0x82 //if SYSCLK<20MHz
- #define CMD_IDLE 0 //????
- #define CMD_READ 1 //IAP?????
- #define CMD_PROGRAM 2 //IAP??????
- #define CMD_ERASE 3 //IAP??????
- #define data_num_addr 0x0000
- #define data_addr 0x0200
- extern bit input_or_finish_flag; //聲明外部變量,用來判斷input或者finish鍵是否按下,0表示無按下,1表示有按下
- extern unsigned char xdata t_ku[300]; //用這個數組來緩存從flash中讀取的點陣信息
- void Delay(unsigned char n); //上面對于位變量的外部引用,需要加上變量類型bit
- void IapIdle();
- unsigned char IapReadByte(unsigned int addr);
- void IapProgramByte(unsigned int addr, unsigned char dat);
- void IapEraseSector(unsigned int addr);
- unsigned char code infro1[240]={
- 0x00,0x00,0x10,0x40,0x10,0x20,0x10,0x10,0x10,0x10,0x10,0x28,0x11,0x44,0x16,0x42,
- 0x10,0x41,0x90,0x40,0x50,0x40,0x30,0x40,0x10,0x40,0x00,0x40,0x00,0x40,0x00,0x00,/*"之",0*/
- …………
- …………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/*" ",6*/
- void Delay10ms() //@11.0592MHz
- {
- unsigned char i, j;
- _nop_();
- _nop_();
- i = 108;
- j = 145;
- do
- {
- while (--j);
- } while (--i);
- }
- void Delay(unsigned char i) //@11.0592MHz
- {
- unsigned char j;
- j = 200;//200-215下眼看不怎么閃 220-230,正眼看不怎么閃
- do
- {
- while (--j);
- } while (--i);
- }
- void sendata595(unsigned char i,unsigned char i2)
- {
- unsigned char j;
- P1=P1&0xbf;
- for(j=0;j<8;j++)
- {
- P1&=0Xdf;
- P1=(P1&0Xef)|((i&0x80)>>3);
- P1|=0x20;
- i<<=1;
- }
- for(j=0;j<8;j++)
- {
- P1&=0Xdf;
- P1=(P1&0Xef)|((i2&0x80)>>3);
- P1|=0x20;
- i2<<=1;
- }
- P1=P1|0x40;
- }
- void infro_display( unsigned char i )//當數據存儲區達到8個字或者沒有存儲的信息就用來顯示操作信息
- {
- unsigned int j , n, j2=0 ;
- unsigned char i2 ;//用來控制循環顯示次數
- unsigned char *table2 ;
- unsigned char c ;//顯示一板字時的刷新次數
- switch(i)
- {
- case 1: j2 = 208; table2 = infro1;break;
- case 2: j2 = 416; table2 = infro2;break;
- case 3: j2 = 176; table2 = infro3;break;
- }
- for(i2=0;i2<2;i2++)//循環顯示兩次
- {
- if( j2==176)//如果是顯示“淮工光信秦帥”則一直顯示,直到input或者finish
- {
- i2 = 0;
- }
- for(j=0;j<j2;j+=2)
- {
- if( input_or_finish_flag == 1)
- {
- return;//如果輸入鍵(input)按下,或者結束鍵(finish)按下,則結束此函數
- }
- for(c=0;c<22;c++)//顯示一板字時的刷新次數
- {
- n=j;
- P1&=0xf0;
- for(i=0;n<32+j;n=n+2,i++)
- {
- sendata595(table2[n],table2[n+1]);
- P1=( (P1&0xf0)|i );
- P17 = 0;
- Delay(2);
- P17 = 1;
- }
- }
- }
- }
- }
- void pailie(unsigned char*w,unsigned char k)
- {
- unsigned char t=0,i,j;
- for(i=0;i<k-1;i++)
- for(j=0;j<k-1-i;j++)
- {
- if(w[j]>w[j+1])
- {
- t = w[j];
- w[j] = w[j+1];
- w[j+1] = t;
- }
- }
- }
- void convert_to_595( unsigned char *q)
- {
- unsigned char k, i, t, t2, j,a[32]={0x00};
- for(i=0; q[i]!=0xff; i++); //統計出數組內元素的個數
- pailie(q , i) ;
- i=0;
- t=(q[0]&0xf0)>>4;
- j=(q[0]&0x0f);
- t2=t;
- for(;t>0;t--,i=i+2)
- {
- a[i]=0x00 ;
- a[i+1]=0x00 ;
- }
- a[i] |= (0x01<<j );
- for(k=1; q[k]!=0xff; k++)
- {
- t=( q[k]&0xf0 )>>4;
- j=( q[k]&0x0f ) ;
- if( t2 != t )
- {
- i=i+2;
- for( ;i<( t+t ); i=i+2)
- {
- a[i] = 0x00 ;
- a[i+1]=0x00 ;
- }
- t2 = t;
- }
- if( j < 8 )
- {
- a[i] |= ( 0x01<< j ) ;
- }
- else
- {
- a[i+1] |= ( 0x01<<(j-8) );
- }
- }
- for( i=0; i<32;i++)
- {
- q[i] = a[i];
- }
- q[32] = 0xff;
- }
-
- bit save_data( unsigned char *p )
- {
- static unsigned char save_data_num = 0;
- bit y_n_flag =0;//操作成功或失敗的標志 1表示成功,0代表失敗
- unsigned int i, j = 0;
- while( (j<5) && (y_n_flag == 0) )
- {
- j++;
- IapEraseSector(data_num_addr);//首先擦除第一與第二個扇區的原始數據
- if( save_data_num == 0 )
- IapEraseSector(data_addr);//首先擦除第一與第二個扇區的原始數據
- y_n_flag = 1;
- for(i=0; i<2; i++)
- {
- if (IapReadByte(data_num_addr+i) != 0xff)
- {
- y_n_flag = 0;
- break;
- }
- }
-
- if( save_data_num == 0 )
- {
- for(i=0; i<512; i++)
- {
- if ( IapReadByte(data_addr+i) != 0xff )
- {
- y_n_flag = 0;
- break;
- }
- }
- }
- }
- if( y_n_flag == 0 )
- {
- return 0;//提前結束此函數,因為擦除操作不成功
- }
- Delay(1);
-
- i=0;
- j=0;
- save_data_num ++;
-
- if( save_data_num == 9 )//如果已經保存了8個數,則清除這8個數
- {
- save_data_num = 1;
- IapEraseSector(data_num_addr);
- IapEraseSector(data_addr);
- y_n_flag = 0 ;
- while(( j<5) && ( y_n_flag == 0))
- {
- y_n_flag = 1;
- for(i=0; i<2; i++)
- {
- if ( IapReadByte(data_num_addr+i) != 0xff )
- {
- y_n_flag = 0;
- break;
- }
- }
- if( y_n_flag != 0)
- {
- for( i=0; i<300; i++) //因為最多只是用到了256個
- {
- if ( IapReadByte(data_addr+i) != 0xff )
- {
- y_n_flag = 0;
- break;
- }
- }
- }
- }
- if( y_n_flag == 1 )
- {
- infro_display( 1 );//循環顯示兩次“之前數據已刪”
- }
- else
- {
- infro_display( 2 );//循環顯示兩次“數據數據刪除失敗,數據未保存”
- save_data_num = 0;
- return y_n_flag;
- }
-
- }
- for( j=0; p[j] != 0xff; j++ )//將收集數組里面的0xfe刪除(0xfe是用來填充的)
- {
- if( p[j] == 0xfe )
- {
- i = j;
- for(;p[i] != 0xff; i++)
- {
- p[i]=p[i+1] ;
- }
- if(j>0) j=j-1;
- }
- }
- convert_to_595(p);//如果前面的塊刪除操作成功,則開始轉化字庫
- IapProgramByte(data_num_addr, save_data_num);//在0x0000處寫上保存數據的個數
- for( j=(save_data_num-1)*32,i=j; i<j+32; i++ )
- {
- IapProgramByte(data_addr+i, p[(i%32)]);//將點陣數據保存到第二扇區里
- }
-
- return y_n_flag;//若值為0,則說明未保存成功,值為1,則保存成功
- }
- void save_data_display(unsigned char *p3,unsigned int i3)
- {
- unsigned int j = 0,n ;
- unsigned char i,c ;
- while(1) //一直顯示直到input或者finish按下
- {
- for(j=0; j<=i3; j+=2)
- {
- if( i3 <33 )//代表只有一個數的時候,j=0,能讓其靜態顯示
- {
- j = 0;
- }
- if( input_or_finish_flag == 1)
- {
- return;//如果輸入鍵(input)按下,或者結束鍵(finish)按下,則結束此函數
- }
- for(c=0;c<22;c++)//顯示一板字時的刷新次數
- {
- n=j;
- P1&=0xf0;
- for(i=0;n<32+j;n=n+2,i++)
- {
- sendata595(p3[n],p3[n+1]);
- P1=( (P1&0xf0)|i );
- P17 = 0;
- Delay(2);
- P17 = 1;
- }
- }
- }
- }
- }
- void data_display()
- {
- unsigned int i,j;
- i = IapReadByte( data_num_addr);
- if ( i == 0xff) //若沒有存儲的數據,則循環顯示“淮工光信秦帥” 可以按input或者finish鍵退出
- {
- infro_display(3 );
- }
- else if( i >=1)
- {
- i = i*32; //i<256
- for( j=0; j<i ; j++)//若存了不只一個數,則移屏顯示這些數 可以按input或者finish鍵退出
- {
- t_ku[j] = IapReadByte( data_addr+j);
- }
- for(; j<32+i;j++) //為了讓其顯示更流暢
- {
- t_ku[j] =0x00;
- }
- save_data_display( t_ku,i); //若i>32則說明是移動顯示
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
0.png (42.34 KB, 下載次數: 80)
下載附件
2018-9-3 15:44 上傳
所有資料51hei提供下載:
代碼.rar
(81.09 KB, 下載次數: 69)
2018-9-3 13:24 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|