?? pic18 單片機(jī)學(xué)習(xí)(程序?qū)嵗?txt
字號(hào):
PIC18 單片機(jī)學(xué)習(xí)(程序?qū)嵗?
說(shuō)明:
18F基本模塊初始化程序均在內(nèi),且測(cè)試通過(guò),主程序可以調(diào)用各個(gè)程序!
編譯器使用PICC18
//程序主要用于18F單片機(jī)學(xué)習(xí)
#include <pic18.h> //18系列單片機(jī)頭文件
//-------------函數(shù)定義--------------
void delay(unsigned int rr);
void timer1(void);
void SPI_Iint(void); //串行SPI輸出設(shè)置函數(shù)
void display(void);
void i2cint(void); //i2c總線初始化程序
void c64R(void); //i2c接口的EEPROM存儲(chǔ)器(讀程序)
void c64W(void); //寫程序
void Start(void); //起始位發(fā)送函數(shù)
void Stop(void); //停止位發(fā)送函數(shù)
void WriteWait(void); //等待函數(shù)
void Senddata(unsigned char data); //數(shù)據(jù)發(fā)送函數(shù)
void Restart(void); //重復(fù)啟動(dòng)函數(shù)
void Datain(void); //數(shù)據(jù)讀入
void Uartint(void); //通用同步/異步收發(fā)器初始化程序
void Udatas(unsigned char dad); //UART數(shù)據(jù)發(fā)送
void Uartrs(void); //串口接收數(shù)據(jù)發(fā)送函數(shù)
void ADint(void); //AD模塊初始化
void shuchai(void);
//-----------數(shù)據(jù)寄存器定義----------
const unsigned char table[10]={0xee,0x82,0xdc,0xd6,0xb2,0x76,0x7e,0xc2,0xfe,0xf6}; //顯示段碼
unsigned char buf[5]; //顯示緩存
unsigned char receive[10]; //定義接收緩存
unsigned char dd; //定時(shí)器0,中斷計(jì)數(shù)寄存器
unsigned char save;
unsigned char conet;
unsigned char *Counter; //接收數(shù)據(jù)指針
unsigned char DADh; //AD緩存,
unsigned char DADl;
unsigned int Dat;
unsigned int Dat1; //保存上次的AD轉(zhuǎn)換值,用于比
volatile bit DADflage; //AD轉(zhuǎn)換標(biāo)志
volatile bit I2Cerror; //I2C錯(cuò)誤標(biāo)志
volatile bit Uartsend; //異步串口數(shù)據(jù)發(fā)送允許
union //聯(lián)合體用來(lái)對(duì)C64的地址進(jìn)行操作!
{
unsigned char dizhi[2];
unsigned int Adress;
}add;
#define AddLow add.dizhi[0]
#define AddHigh add.dizhi[1]
#define ADDss add.Adress
//***********************************
//初始化
//***********************************
void PICint()
{
SWDTEN=1; //禁止看門狗,18F看門狗是可以用軟件控制開(kāi)啟的!
INTCON=0;
ADCON1=0x07; //AD端口全部始能為數(shù)字IO口
TRISB7=0; //設(shè)置為輸出端口
RB7=0;
PIE1=0;
PIE2=0;
PIE3=0;
buf[0]=0;
buf[1]=0;
buf[2]=0;
buf[3]=0;
//CMCON=0x07; //關(guān)閉比較器,18F2680沒(méi)有比較器
}
//***********************************
//高優(yōu)先級(jí)中斷函數(shù)
//***********************************
void interrupt HI_ISR()
{
if(TMR0IF&TMR0IE) //確認(rèn)是定時(shí)器0中斷
{
dd++;
TMR0IF=0;
TMR0H=0xd8; //10ms定時(shí)常數(shù)
TMR0L=0xef;
if(dd==100)
{
dd=0;
buf[0]++;
if(buf[0]==10)
{
buf[0]=0;
buf[1]++;
if(buf[1]==10)
{
buf[1]=0;
buf[2]++;
if(buf[2]==10)
{
buf[2]=0;
buf[3]++;
if(buf[3]==10)
{
buf[3]=0;
}
}
}
}
}
}
if(ADIF) //判斷是否是AD轉(zhuǎn)換中斷
{
ADIF=0; //清0
DADh=ADRESH;
DADl=ADRESL;
Dat=256*DADh+DADl;
if(((Dat-Dat1)==1)||((Dat1-Dat)==1))
{
Dat=Dat1;
}
DADflage=1;
}
}
//***********************************
//低優(yōu)先級(jí)中斷函數(shù)
//***********************************
void interrupt low_priority LOW_ISR()
{
if(RCIF&RCIE) //如果是串口接收中斷的話,則進(jìn)入中斷處理
{
RCIF=0; //清中斷標(biāo)志
*Counter=RCREG;//讀取數(shù)據(jù)到數(shù)組
Counter++;
if((Counter-&receive[0])==10)
{
Counter=&receive[0];
Uartsend=1;
}
}
}
//***********************************
//定時(shí)器0初始化子程序
//***********************************
void timer1()
{
IPEN=1; //打開(kāi)高低優(yōu)先級(jí)
T0CON=0x09; //把定時(shí)器0設(shè)定為16位定時(shí)器,內(nèi)部時(shí)鐘觸發(fā),不使用分頻器
TMR0IE=1; //允許定時(shí)器0溢出中斷
TMR0IF=0; //清除中斷標(biāo)志
TMR0IP=1; //設(shè)定定時(shí)器0中斷為高優(yōu)先級(jí)
TMR0H=0xD8; //定時(shí)常數(shù)
TMR0L=0xef;
GIE=1;
PEIE=1;
TMR0ON=1;
}
//***********************************
//AD轉(zhuǎn)換初始化函數(shù)
//***********************************
void ADint() //使用于18F2680!
{
ADCON0=0x01; //AD轉(zhuǎn)換速率為Fosc/4,并使能AD轉(zhuǎn)換模塊
ADCON1=0x0e; //選擇為右對(duì)齊模式,并且使能AD0為模擬通道
ADCON2=0x91;
TRISA=1; //RA0為輸入模式
ADIF=0;
ADIE=1; //中斷使能
IPEN=1; //使能高低中斷優(yōu)先級(jí)
ADIP=1; //AD轉(zhuǎn)換設(shè)置為高優(yōu)先級(jí)中斷
GIE=1; //開(kāi)總中斷以及外部中斷
PEIE=1;
DADflage=0;
}
//***********************************
//I2C初始化函數(shù)
//***********************************
void i2cint()
{
SSPCON1=0x08; //允許串口工作,I2C主控方式,時(shí)鐘=Fosc/[4*(SSPADD+1)]
RC4=1; //設(shè)置為輸入
RC3=1;
SSPADD=7; //時(shí)鐘頻率約為0.125M
SSPSTAT=0x80; //關(guān)閉標(biāo)準(zhǔn)速度方式
SSPCON2=0;
SSPEN=1; //使能串口(SSP模塊)
I2Cerror=0;
}
//***********************************
//SPI初始化程序
//***********************************
void SPI_Iint()
{
TRISC5=0; //SDO引腳
TRISC4=1; //SDI引腳
TRISC3=0; //SCK,串行時(shí)鐘輸出引腳
TRISA5=0; //RA5為從動(dòng)SS端
SSPCON1=0x30; //使能串口,高電平為空閑狀態(tài),并且發(fā)送頻率為fose/4,主控方式;
SSPSTAT=0xc0; //時(shí)鐘下降沿發(fā)送數(shù)據(jù)!
SSPIF=0;
conet=0;
}
//***********************************
//通用同步/異步收發(fā)器(UART)初始化
//***********************************
void Uartint()
{
TXSTA=0x04; //設(shè)置為高速異步,方式
RCSTA=0x80; //使能UART
TRISC6=0; //設(shè)置為輸入,對(duì)外部呈現(xiàn)高阻態(tài)
TRISC7=1;
SPBRG=25; //設(shè)置波特率為9600
//波特率計(jì)算公式
//1.同步方式:波特率=Fosc/[4(X+1)]
//2.異步方式:BRGH=0:波特率=Fosc/[64(x+1)]
// BRGH=1:波特率=Fosc/[16(x+1)]
IPEN=1; //開(kāi)中斷優(yōu)先級(jí)
RCIP=0; //串口接收使能為低優(yōu)先級(jí)
RCIE=1; //串口接收中斷使能
RCIF=0;
TXIE=0; //禁止發(fā)送中斷
GIE=1; //開(kāi)總中斷和外圍中斷
PEIE=1;
TXEN=1; //使能串口發(fā)送
CREN=1; //使能串口接收 ,注意18F是CREN而不是RCEN,編譯器都認(rèn)為是正確的但是RCEN不管用!
Counter=&receive[0];//把數(shù)組的首地址給指針
Uartsend=0;
}
//***********************************
//AD轉(zhuǎn)換函數(shù)
//***********************************
void ADchange()
{
ADCON0=ADCON0|0x02; //啟動(dòng)AD轉(zhuǎn)換
if(DADflage) //如果AD轉(zhuǎn)換完成,這里采用
{
DADflage=0;
shuchai();
display();
}
}
//***********************************
//AD 數(shù)據(jù)拆分
//***********************************
void shuchai()
{
unsigned int i;
Dat1=Dat; //保存這次的計(jì)數(shù)值
i=Dat;
buf[3]=i/1000; //取出千位
i=i%1000; //取出百位數(shù)
buf[2]=i/100; //取出百位數(shù)
i=i%100; //取出十位數(shù)
buf[1]=i/10;
i=i%10;
buf[0]=i;
}
//***********************************
//Uart receive data send
//***********************************
void Uartrs()
{
if(Uartsend)
{
unsigned char i;
Uartsend=0;
for(i=0;i<10;i++)
{
Udatas(*Counter);
Counter++;
}
Counter=&receive[0]; //重新初始化
}
}
//***********************************
//Uart 數(shù)據(jù)發(fā)送子程序
//***********************************
void Udatas(unsigned char dad)
{
TXREG=dad;
while(1)
{
if(TXIF==1) break; //等待數(shù)據(jù)寫入
}
delay(80);
}
//***********************************
//I2C寫子程序
//***********************************
void c64W()
{
Start();
if(I2Cerror==1)
{
I2Cerror=0;
return; //返回防止死循環(huán)
}
Senddata(0xa0); //發(fā)送尋址地址,以及寫操作地址!
if(I2Cerror==1)
{
I2Cerror=0;
Stop(); //錯(cuò)誤處理
return; //返回防止死循環(huán)
}
Senddata(0x00); //發(fā)送高位地址
if(I2Cerror==1)
{
I2Cerror=0;
Stop(); //錯(cuò)誤處理
return; //返回防止死循環(huán)
}
Senddata(0x40); //發(fā)送地址低字節(jié)
if(I2Cerror==1)
{
I2Cerror=0;
Stop(); //錯(cuò)誤處理
return; //返回防止死循環(huán)
}
Senddata(0x55); //發(fā)送數(shù)據(jù)
if(I2Cerror==1)
{
I2Cerror=0;
Stop(); //錯(cuò)誤處理
return; //返回防止死循環(huán)
}
Stop();
}
//***********************************
//I2C讀數(shù)據(jù)程序
//***********************************
void c64R()
{
Start();
if(I2Cerror==1)
{
I2Cerror=0;
return; //返回防止死循環(huán)
}
Senddata(0xa0); //發(fā)送尋址地址,以及寫操作地址!
if(I2Cerror==1)
{
I2Cerror=0;
Stop(); //錯(cuò)誤處理
return; //返回防止死循環(huán)
}
Senddata(0x00); //發(fā)送高位地址
if(I2Cerror==1)
{
I2Cerror=0;
Stop(); //錯(cuò)誤處理
return; //返回防止死循環(huán)
}
Senddata(0x40); //發(fā)送地址低字節(jié)
if(I2Cerror==1)
{
I2Cerror=0;
Stop(); //錯(cuò)誤處理
return; //返回防止死循環(huán)
}
Restart(); //發(fā)送重新起始位
Senddata(0xa1); //發(fā)送讀命令
if(I2Cerror==1)
{
I2Cerror=0;
Stop(); //錯(cuò)誤處理
return; //返回防止死循環(huán)
}
Datain();
Stop();
if(save==0x55)
{
RB7=1;
}
conet++;
}
//***********************************
//I2C重復(fù)啟動(dòng)
//***********************************
void Restart()
{
RSEN=1;
while(1)
{
if(SSPIF==1) break;
}
SSPIF=0;
}
//***********************************
//I2C數(shù)據(jù)寫等待
//***********************************
void WriteWait()
{
while(1)
{
Start(); //在數(shù)據(jù)寫入時(shí)間,如果在給器件發(fā)送數(shù)據(jù)不會(huì)有響應(yīng)
Senddata(0xa0);
Stop();
if(I2Cerror==0) break; //等待數(shù)據(jù)寫入,=0則有應(yīng)答位產(chǎn)生
}
}
//***********************************
//I2C起始位發(fā)送函數(shù)
//***********************************
void Start()
{
unsigned char i=0;
SEN=1; //起始位發(fā)送
while(1)
{
i++;
if(SSPIF==1) break;
if(i==200) //防止死循環(huán)
{
i=0;
I2Cerror=1;
break;
}
}
SSPIF=0;
}
//***********************************
//I2C停止位發(fā)送
//***********************************
void Stop()
{
PEN=1;
while(1)
{
if(SSPIF==1) break;
}
SSPIF=0;
}
//***********************************
//I2C數(shù)據(jù)發(fā)送函數(shù)
//***********************************
void Senddata(unsigned char data)
{
unsigned char i;
SSPBUF=data; //發(fā)送數(shù)據(jù)
while(1)
{
if(SSPIF==1) break;
}
SSPIF=0;
for(i=0;i<10;i++)
{}
if(ACKSTAT) //如果沒(méi)有發(fā)出應(yīng)答信號(hào)
{
I2Cerror=1;
}
else //如果發(fā)出應(yīng)答信號(hào)
{
I2Cerror=0;
}
}
//***********************************
//I2C 數(shù)據(jù)讀入函數(shù)
//***********************************
void Datain()
{
RCEN=1;
while(1)
{
if(SSPIF==1) break;
}
SSPIF=0;
save=SSPBUF; //讀數(shù)
ACKDT=1; //發(fā)送非應(yīng)答位
ACKEN=1;
while(1)
{
if(SSPIF==1) break;
}
SSPIF=0;
}
//***********************************
//164顯示程序
//***********************************
void display() //164顯示程序,用SPI端口發(fā)送數(shù)據(jù)
{
unsigned char i;
unsigned char y,t; //傳輸完四個(gè)字節(jié)
for(i=0;i<4;i++)
{
y=buf[i];
t=table[y];
SSPBUF=t;
while(1)
{
if(SSPIF) break;
}
SSPIF=0;
}
}
//***********************************
//延時(shí)函數(shù)
//***********************************
void delay(unsigned int rr) //延時(shí)函數(shù)
{
unsigned int asd;
for(asd=0;asd<rr;asd++)
{}
}
//***********************************
//主函數(shù)
//***********************************
void main()
{
PICint(); //初始化函數(shù)
//Uartint(); //異步串行口初始化
//SPI_Iint();
//ADint(); //AD模塊初始化
//timer1();
//display();
//i2cint(); //I2C初始化
//c64W(); //往C64里寫一次數(shù)據(jù)
//WriteWait();
//c64R(); //讀C64里
while(1)
{
//CLRWDT();
//delay(20000);
CLRWDT();
RB7=1;
CLRWDT();
SLEEP(); //等待看門狗復(fù)位
RB7=0;
delay(20000);
CLRWDT();
}
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -