|
8樓
樓主 |
發表于 2009-9-4 19:22:39
|
只看該作者
mcu 程序
/*******************************************
單片機顯卡測試程序
硬件規格:
stc51單片機主控,cpld+sdram實現顯卡硬件,
這是stc51的主控程序。
by
wangkj@yahoo.com
qq:1248780
群:630571
create 2009-07-10
version 0.1
STC5205AD
*******************************************/
//#include "REG51F.H"
//#include
#include
#include
#include
sbit MCU_IR_PWM = P3^7;
sbit _CS = P1^4; // SPI總線的片選信號線
sbit SPCK= P1^7; // SPI總線的鐘信號線
sbit MOSI= P1^5; // SPI總線的串行數據輸出線
sbit EA0 = P1^6; // 地址/數據選擇
#define TRUE 1
#define FALSE 0
#define WIDTH 1024
#define HIGH 768
//#define nop() _nop_
volatile unsigned int data TimerCounter=0;
/********************************************/
/* 定時器 0 中斷服務 */
/* 說明: 100us 中斷一次, 優先級最高 */
/********************************************/
void Timer0_Int(void) interrupt 1 using 1 //自動reload方式,10us
{
TimerCounter++;
}
//延時1ms
void nop()
{
unsigned char data i;
for (i=0;i<1;i++)
{
}
// _nop_ ;
}
void udelay(void)
{
unsigned char data i;
for (i=0;i<10;i++);
}
void delay1ms(void)
{
unsigned int data OldTimerCounter;
OldTimerCounter = TimerCounter;
while((TimerCounter-OldTimerCounter)<100)//
{ //如果調試,請把1換成不同到值,1是延時1ms,誤差很小
MCU_IR_PWM=~MCU_IR_PWM;
}
}
/*從SPI總線上讀入一個字節
unsigned int spi_read16(void)
{
unsigned int data inData;
unsigned char data i;
for(i=0; i<8; i++) // 移8次
{
SCK = 0; // 拉低時鐘線
inData <<= 1;
inData |= MO; // 從SPI總線的數據輸出線SO上讀入一位
SCK = 1; // 拉高時鐘線
}
return(inData);
} */ // python: for i in range(1,15): hex(i*1024+i)
/*輸出一個字節到SPI總線上*/
void spi_write8(unsigned char data outData)
{
char i,j;
for(i=0; i<8; i++)
{
SPCK = 0;
if ((outData & 0x80)==0)
MOSI=0;
else
MOSI=1;
//delay1ms();
for(j=0;j<3;j++);
SPCK = 1;
for(j=0;j<3;j++);
//delay1ms();
outData <<= 1;
/* outData <<= 1;
SPCK = 1;
MOSI = CY;
SPCK = 0; */
}
SPCK = 0;
/* for(i=0; i<8; i++) // 移8次
{
// outData <<= 1;
// MOSI = CY;
SPCK = 1;
if ((outData & (0x80>>i))==0)
MOSI=0;
else
MOSI=1;
// 移出一位,送出至SPI總線的數據輸出MOSI上
SPCK = 0;
} */
}/*讀SPI器件的狀態*/
void spi_write16(unsigned int outData)
{
union
{
unsigned int Data16;
unsigned char Data8[2];
} spi8;
spi8.Data16=outData;
spi_write8(spi8.Data8[0]); //high
spi_write8(spi8.Data8[1]); //low
}
void cursor(unsigned int x,y) //設置顯存地址 8M 尋址空間。
{
//int i;
union
{
unsigned long int addr;
unsigned int addr_HL[2];
} addr_union;
addr_union.addr=1L*(long)y*WIDTH+(long)x;
EA0=1;//set cmd status
//addr=272*y+x;
spi_write16(addr_union.addr_HL[0]); //high
spi_write16(addr_union.addr_HL[1]); //low
EA0=0;//set data status PutCmd(0);//reset display ram pointer to 0
}
void clr_scr(void)
{
unsigned char i,j,k;
cursor(0,0);
//addr= 1L*WIDTH*HIGH*8*2;
MOSI=0;
for(i=0;i<97*2;i++)
for(j=0;j<255;j++)
for(k=0;k<255;k++)
{SPCK=1;SPCK=0;}
}
//主程序
void main(void)
{
unsigned int i,j,k;//OldTimerCounter;
unsigned long int x,y;
// unsigned char ch;// cmd,
// unsigned int j;
P1M0=0x00; //準雙向口
P1M1=0x00;
// AUXR = 0x40; //可能不能位尋址以及OR,AND 操作,待驗證
//AUXR=0x20;//6x UART 速度
AUXR=0x40|0x80; //T0,T1 12X
// AUXR=0x40;
//T0 正常 T1/1 12倍速, UART正常 ,禁用ADC,SPI,低壓中斷。
/***********************************************
AUXR 地址8EH 復位值=xxxx xx00B
7 6 5 4 3 2 1 0
T0x12 T1x12 UART_M0x6 EADCI ESPI ELVDI - - 0000,00xx
定時器0 和定時器1:
STC12C5410AD 和STC12C2052AD 系列是 1T 的8051 單片機,為了兼容傳統8051,定時器0 和定時器1 復
位后是傳統8051 的速度,即12 分頻,這是為了兼容傳統8051。但也可不進行12 分頻,實現真正的1T。
T0x12: 0, 定時器0 是傳統8051 速度,12 分頻;1, 定時器0 的速度是傳統8051 的12 倍,不分頻
T1x12: 0, 定時器1 是傳統8051 速度,12 分頻;1, 定時器1 的速度是傳統8051 的12 倍,不分頻
如果UART 串口用定時器1 做波特率發生器,T1x12 位就可以控制UART 串口是12T 還是1T 了。
UART 串口的模式0:
STC12C5410AD 和STC12C2052AD 系列是 1T 的8051 單片機,為了兼容傳統8051,UART 串口復位后是兼容
傳統8051 的。
UART_M0x6: 0, UART 串口的模式0 是傳統12T 的8051 速度,12 分頻;
1, UART 串口的模式0 的速度是傳統12T 的8051 的6 倍,2 分頻
如果用定時器T1做波特率發生器時,UART串口的速度由T1的溢出率決定
EADCI: 0, 禁止A/D 中斷; 1,允許A/D 中斷
ESPI: 0, 禁止SPI 中斷; 1,允許SPI 中斷
ELVDI: 0, 禁止低壓中斷; 1,允許低壓中斷
5V 單片機,3.7V 以下為低壓,3V 單片機,2.4V 以下為低壓,
如ELVDI=1(允許低壓中斷),則會產生低壓中斷,現版本無低壓檢測中斷,是低壓復位。
STC12C5410AD 系列無低壓檢測中斷,只有STC12C2052AD 系列單片機才有低壓檢測中斷。
*************************************************/
// 28.636晶振,bps 2400 誤差 0.21% STC5410可以12倍速T1,
// T0 標準51方式,做 1ms 基準時間用
PCON=0x80; //12倍T1 * 2 倍 bps 2400*12*2=57600
// PCON=0x00; //正常操作,沒有倍速
/***********************************************
7 6 5 4 3 2 1 0
SMOD SMOD0 LVDF POF GF1 GF0 PD IDL
POF:上電復位標志位,單片機停電后,上電復位標志位為1 ,可由軟件清0 。
實際應用:要判斷是上電復位(冷啟動),還是外部復位腳輸入復位信號產生的復位,還是內部看門狗復位
P D: 將其置1 時,進入Power Down 模式,可由外部中斷低電平觸發或下降沿觸發中斷模式喚醒。
進入掉電模式時,外部時鐘停振,CPU、定時器、串行口全部停止工作,只有外部中斷繼續工作。
IDL:將其置1,進入IDLE 模式(空閑),除CPU 不工作外,其余仍繼續工作,可由任何一個中斷喚醒。
現C 版本開始大量供貨,C 版本IDLE 模式可正常使用(原A 版本和B 版本建議不要用IDLE 模式)。
GF1,GF0: 兩個通用工作標志位,用戶可以任意使用。
SMOD: 波特率倍速位,置1,串口通訊波特率快一倍
***********************************************/
// SMOD=1;
IE=0x00; //disable all interrupt
/************************************************
IE(0A8H)
7 6 5 4 3 2 1 0
EA EC ET2 ES ET1 EX1 ET0 EX0
使能位=1 使能中斷
使能位=0 禁止中斷
位標號功能
IE.7 EA 全局禁止位如果EA=0 禁止所有中斷如果EA=1 通過置
位或清除使能位對應的每個中斷被使能或禁止
IE.6 EC PCA中斷使能位
IE.5 ET2 定時器2 中斷使能位
IE.4 ES 串行口中斷使能位
IE.3 ET1 定時器1 中斷使能位
IE.2 EX1 外部中斷1 使能位
IE.1 ET0 定時器0 中斷使能位
IE.0 EX0 外部中斷0 使能位
*************************************************/
IP=0x02; //Timer0 is first level of interrupt
/**********************************************
IP(0B8H) 7 6 5 4 3 2 1 0
PT2 PS PT1 PX1 PT0 PX0
中斷優先級控制位=1 定義為高優先級中斷
中斷優先級控制位=0 定義為低優先級中斷
IP.6 PPC PCA中斷優先級控制位
IP.5 PT2 定時器2 中斷優先級控制位
IP.4 PS 串行口中斷優先級控制位
IP.3 PT1 定時器1 中斷優先級控制位
IP.2 PX1 外部中斷1 中斷優先級控制位
IP.1 PT0 定時器0 中斷優先級控制位
IP.0 PX0 外部中斷0 中斷優先級控制位
************************************************/
TMOD=0x22; //T0,T1 8 bit Reload
/***********************************************
TMOD 地址:89H 不可位尋址 復位值:00H
7 6 5 4 3 2 1 0
GATE C/T M1 M0 GATE C/T M1 M0
定時器1 定時器0
位符號 功能
TMOD.7/ GATE TMOD.7 控制定時器1,置1 時只有在INT1 腳為高及TR1 控制位置1 時才可打開定時器/ 計數器1。
TMOD.3/ GATE TMOD.3 控制定時器0,置1 時只有在INT0 腳為高及TR0 控制位置1 時才可打開定時器/ 計數器0。
TMOD.6/ C/T TMOD.6 控制定時器1 用作定時器或計數器,清零則用作定時器(從內部系統時鐘輸入),
置1 用作計數器(從T1/P3.5 腳輸入)
TMOD.2/ C/T TMOD.2 控制定時器0 用作定時器或計數器,清零則用作定時器(從內部系統時鐘輸入),置1
用作計數器(從T0/P3.4 腳輸入)
TMOD.5/TMOD.4 M1、M0 定時器定時器/計數器1模式選擇
0 0 13位定時器/ 計數器,兼容8048 定時器模式,TL1 只用低5 位參與分頻,TH1 整個8 位全用。
0 1 16位定時器/ 計數器,TL1、TH1 全用
1 0 8 位自動重裝載定時器,當溢出時將TH1 存放的值自動重裝入TL1。
1 1 定時器/ 計數器1 此時無效(停止計數)。
TMOD.1/TMOD.0 M1、M0 定時器/ 計數器0 模式選擇
0 0 13位定時器/ 計數器,兼容8048 定時器模式,TL0 只用低5 位參與分頻,TH0 整個8 位全用。
0 1 16位定時器/ 計數器,TL0、TH0 全用
1 0 8位自動重裝載定時器,當溢出時將TH0 存放的值自動重裝入TL0。
1 1 定時器0 此時作為雙8 位定時器/ 計數器。TL0 作為一個8 位定時器/ 計數器,通過標準定時器0
的控制位控制。TH0 僅作為一個8 位定時器,由定時器1 的控制位控制。
***********************************************/
TH1=BAUD_2400; //設置串口的波特率為2400 for OSC 28.636Mhz//19200 for 29.08M
TL1=BAUD_2400; //It Will be 2400*12*2 = 57600 //19200*6-115200 6x UART模式
/**********************************************
串行口在方式1和方式3的波特率可變,與定時器T1或T2的溢出速率有關。51子系列
’常用定時器T1作為波待率發生器,這時方式1和方式3的波特率由定時器Tl的溢出率
確定
***********************************************/
SCON=0x42; //8bit variable,無多機通訊,REN=0,disable receive and set TI to generate serial send interupt
//else the serial interupt will not work.
/**********************************************
sc0N是一個可位尋址的專用寄存器,用來設定串行口的工作方式、控制串行口的接收
’發送以及狀態標志。SCON的字節地址為98H,位地址為98H一9FH。其格式如下:
D7 D6 D5 D4 D3 D2 Dl D9
SM0 SM1 SM2 REN TB8 RB8 TI RI
各位的定義說明如下
SMO SCON.7 Serial Port mode specifier.(NOTE 1).
SM1 SCON.6 Serial Port mode specifier.(NOTE 1).
SMO SM1 Mode Description baud Rate
0 0 0 SHIFT REGISTER FOSC/12
0 1 1 8-BitUART Variable
1 0 2 9-BitUART Fosc/64 or Fosc/32
1 1 3 9-BitUART Variable
SM2 SCON.5
在工作方式2和方式3中允許多機通信控制位。若SM 2置1,則允許多機通
信。當串行口以方式2或方式3接收時,若SM2=1,且接收到的第9位數據(RB8)為l,則
接收到的前8位數據送入SBUF,并置位RI產生中斷請求;否則,RI=o,接收到的前8位數
據丟失。而當sM2=o時,則不管RB8是o還是1,都將前8位數據裝入SBUF中,并產生中
斷請求。
在方式1中,若SM2=1,則只有接收到有效的停止位時,RI才置1,否則RI 0
在方式o中,SM2必須為o。
REN SCON.4 允許串行接收位。該位由軟件置位或清除。REN=1時,允許接收;REN=o時,禁止接收
TB8 SCON.3
在工作方式2或方式3時,該位為發送的第9位數據,可按需要由軟件置位或
清零。在許多通信協議中,該位常作為奇偶校驗位。在Mc5—5l多機通信中,TB8的狀態用
來表示發送的是地址幀還是數據幀,TB8=o時,為地址幀,TB8=1時,為數據幀。
RB8 SCON.2
在工作方式2或方式3時,存放接收到的第9位數據,代表著接收效據的某種
特征。例如,可能是奇偶位,或為多機通信中的地址/數據標識位。在方式o中,RB8未用;在
方式1中,若SM2=o,RB8是已接收到的停止位。
TI SCON.1
發送中斷標志。方式0中,串行發送完第8位數據后,由硬件置位;在其它方
式中,在發送停止位開始時,由硬件置位。TI=1時,表示幀發送結束,其狀態既可供軟件查
詢使用,也可申請中斷。在任何方式中,TI都必須由軟件清0。
RI SCON.O
接收中斷標志。在方式o中,接收完第8位數據后,由硬件置位;在其它方式中,
在接收到停止位的中間時由硬件置位。RI=1時,表示幀接收結束,其狀態既可供軟件查詢
使用,也可申請中斷。RI也必須靠軟件清o。
when reset ,SCON=0;
***********************************************/
REN=1; //enable serial receive
TH0=256-111; //1000000/(11.0592*1000*1000/111)=10.04 us
TL0=256-111;
TR0=1;
TR1=1; //TCON=0x50;//0B01010000; //Timer1 enable Timer0 enable,No external INT
ET0=1; //enable Timer0 interupt
// ET1=1; //enable Timer1 interupt
ES=1; //enable serial interupt
EA=1; //enable interupt
/*************************************************
TCON作為定時器/汁數器的技制寄存器,其功能是控制定時器T0或T1的運行或停
止,標志定時器的溢出和中斷情況。
TCON: TIMER/COUNTER CONTROL REGISTER. BIT ADDRESSABLE.
TFl TR1 TFO TRO IE1 IT1 IEO ITO
位地址 8FH 8xH 8DH 8CH 8BH 8AH 89H 88H
(1)TF1(TCON.7):定時器T1溢出標志。TI溢出時,由硬件自動使置1,并向
CPU申請中斷。當進入個斷服務程序時,硬件自動將TFl清0。TFl也可以用軟件清0。
(2)TR1(TCON.6);定時器T1運行控制1位。由軟件來置1或清0。 1啟動工作,0停止。
(3)TF0(TCON.5):定時器T0溢出標志。
(4)TR0(TCON.4):定時器T0控制位
(5)IE1(TCON.3):外部中斷1(INT1)請求標志。
(6)IT1(TCON.2):外部中斷1觸發方式選擇位。
(7)1E0(TCON .l):外部中斷0(INT0)請求標志。
(8)IT0(TCON.0):外部中斷0觸發方式選擇位。當ITo=o時,為電平觸發方式當ITo=1時,為邊沿觸發方式
檢測到由高到低的負跳變,,則置IEo標志為1,表示外部中斷o正在向CPU申請中斷必須保證外部中斷源輸人的高電平
和低電平的持續時間在12個時鐘周期以上
TCON中的低四位(1E1、ITl、IE0,IT0)與中斷有關
TCON.7 Timer 1 overflow flag. Set by hardware when the Timer/Counter 1 overlows.Cleared by hardware
processer vectors to the interrupt service routine.
TCON.6 Timer 1 run control bit. Set/cleared by software to turn Timer/Counter 1 ON/OFF.
TCON.5 Timer O overflow flag. Set by hardware when the Timer/CounterO overflows.Cleared by hsrdware
proceaser vectors to the service routine.
TCON.4 Timer O run control bit. Set/cleared by software to turn Timer/Counter O ON/OFF.
TCON.3 External Interrupt 1 edge flag. Set by hardware when External Interrupt edge is detected.
Cleared by hardware when interrupt is processed.
TCON.2 Interrupt 1 type control bit. Set/cleared by sotlwsre to specify falling edge flow level triggered
External Interrupt.
TCON. 1 External Interrupt O edge flag.Setby hardware when External Interrupt edge deteeted.Cleared
by hardware when interrupt is proeeased.
TCGN.O Interrupt O type control bit. Set/cleared by sotlwsre to specify fsfling edge/low level triggered
External Interrupt.
**************************************************/
char_init();
/* i=0;
for(i=0;i<100;i++)//延時1s,等待所有的機器都啟動
{ send_char(i);
Delay1ms();
}
*/
SPCK=0;
while(1)
{
// if ((char_can_read()>=1))
if ((1))
{
// cmd=get_char();
// if (cmd==0x0a) //pc發送不同的命令字,可以執行不同的操作
// if (cmd=='a') //pc發送不同的命令字,可以執行不同的操作
//for(j=0;j<10000;j++) delay1ms();
//EA0=0;
//delay1ms();
//EA0=1;
//spi_write16(0);
for(j=0;j<1000;j++) //delay
delay1ms();
EA0=1;
spi_write16(0);
spi_write16(0xffff);spi_write16(0xffff);spi_write16(0xffff);spi_write16(0xffff);//reset command
spi_write16(0);
EA0=0;
delay1ms();
//去掉這行,verilog 接收會出錯,開始部分正常(<3000)
/* for(j=0;j<15000;j++) //delay
delay1ms();
clr_scr();
for (x=0;x<1024L*1024L;x++)
{
//EA0=1; //
//EA0=!EA0;
if ((x %5 )==0)
spi_write16(0x07e0);//green//spi_write16(j);
else if ((x % 5)==1)
spi_write16(0xf800);//blue//spi_write16(j);
else if ((x % 5)==2)
spi_write16(0x001f);//red//spi_write16(j);
else if ((x % 5)==3)
spi_write16(0x0000);//black//spi_write16(j);
else if ((x % 5)==4)
spi_write16(0xffff);//white//spi_write16(j);
if (x<160*1024L)
spi_write16(0x07e0);//green
else
if (x<2*160*1024L)
spi_write16(0xf800); //blue/
else
if (x<3*160*1024L)
spi_write16(0);
else
if (x<4*160*1024L)
spi_write16(0xffff);
else
spi_write16(0x001f); //red/
//spi_write16(x>>16);
for(y=0;y<1;y++)
{
// delay1ms();
}
//send_char('.');// send_char(0xd);send_char(0xa);
//clr_scr();
}
spi_write16(0xffff);
for(j=0;j<20000;j++)
delay1ms();
//////////////////////////////////
//for(i=0;i<1024;i++)
while (1)
{
for(i=0;i<768;i++)
{
cursor(i,i);
delay1ms();
spi_write16(0xffff);
}
cursor(0,750);
for (j=0;j<5000;j++) {delay1ms(); spi_write16(0xff);}
cursor(0,0);
for(i=0;i<768;i++)
for (j=0;j<1024;j++)
if (i==j)
spi_write16(0); //for(n=0;n<1;n++);清屏 延時用2足夠了,如果硬件規格高,可以省略。
else
spi_write16(0xffff); //delay1ms();
cursor(0,760);
for (j=0;j<5000;j++) {delay1ms(); spi_write16(0xff00);}
}
for(i=0;i<768;i++)
{
cursor(i,0);
spi_write16(0xffff);
}
for(i=0;i<768;i++)
{
cursor(i,767);
spi_write16(0xffff);
}
for(i=0;i<768;i++)
{
cursor(0,i);
spi_write16(0xffff);
}
for(i=0;i<768;i++)
{
cursor(767,i);
spi_write16(0xffff);
}
for(i=0;i<768;i++)
{
cursor(797,i);
spi_write16(0xffff);
} */
clr_scr();
for(k=5;k<20;k++)
{
cursor(0,0);//clear screen
for(i=0;i<768;i++)
for (j=0;j<1024;j++)
if ((i==j)||(i==j+k*5)||(i%k==0)||(j%k==0)||(i==0)||(j==0)||(j==1023)||(i==767))
spi_write16(0xffff); //for(n=0;n<1;n++);清屏 延時用2足夠了,如果硬件規格高,可以省略。
else
//spi_write16(0x0); //delay1ms();
{
if (i<150)
spi_write16(0x07e0);//green
else
if (i<2*150)
spi_write16(0xf800); //blue/
else
if (i<3*150)
spi_write16(0);
else
if (i<4*150)
spi_write16(0xf800|0x07e0);
else
spi_write16(0x001f); //red/
}
send_char('*');send_char(0xd);send_char(0xa);
}
}
}
// for(i=0;i<1000;i++)//延時1s,等待所有的機器都啟動
// Delay1ms();
// OldTimerCounter = TimerCounter;
// while((TimerCounter-OldTimerCounter)<=20000)//無符號數減法
// {
// }
} |
-
-
src.rar
2009-9-4 19:22 上傳
點擊文件名下載附件
下載積分: 積分 -1
53.58 KB, 下載積分: 積分 -1
|