例程的作用類(lèi)似于函數(shù),但含義更為豐富一些。例程是某個(gè)系統(tǒng)對(duì)外提供的功能接口或服務(wù)的集合。比如操作系統(tǒng)的API、服務(wù)等就是例程;Delphi或C++Builder提供的標(biāo)準(zhǔn)函數(shù)和庫(kù)函數(shù)等也是例程。我們編寫(xiě)一個(gè)DLL的時(shí)候,里面的輸出函數(shù)就是這個(gè)DLL的例程。
可以這么簡(jiǎn)單地來(lái)理解:把一段相對(duì)獨(dú)立的代碼寫(xiě)成單獨(dú)的一個(gè)模塊就是函數(shù)的概念。我們可以在自己的程序中編寫(xiě)很多個(gè)函數(shù),從而實(shí)現(xiàn)模塊化編程。但這些模塊或者說(shuō)函數(shù)并不一定向外輸出(即提供給別的程序使用),只用于當(dāng)前這個(gè)程序里面。此時(shí)這些函數(shù)就僅僅具有獨(dú)立函數(shù)的意義,但不是例程。
pic16f1824代碼例程
main.c
#include 《htc.h》
__CONFIG(FOSC_HS & WDTE_OFF & LVP_OFF);
// int DATA[100][2]=0;
//用于存儲(chǔ)采集過(guò)來(lái)的結(jié)果
long long int xishu1[16]={0,0,0,0}; //用于存儲(chǔ)上位機(jī)發(fā)來(lái)的16個(gè)系數(shù)
bit FLAG_receivefactor=0; //接收標(biāo)志位,如果為一表示本次中斷需要接收系數(shù)
int Factor_number=-1;//系數(shù)編號(hào),表示本次中斷接收的是第幾個(gè)編號(hào)的系數(shù)
long long int real=0;
/****************************************** 串口初始化函數(shù)
******************************************/
void USTRA_init()
{
BRG16=0;//使用8位波特率發(fā)生器
SPBRGL=12;//設(shè)置波特率發(fā)生寄存器的值4800
20SPBRGH=0;
ANSA1=0; //A1引腳被配置為端口或數(shù)字特殊功能
ANSA0=0;//A0引腳被配置為端口或數(shù)字特殊功能
RXDTSEL=1; //備用引腳控制寄存器0的bit7 即RA1上具有RX/DT功能
TXCKSEL=1; //備用引腳控制寄存器0的bit2 即RA0上具有TX/CK功能
TRISA0=0; //配置AO端口為輸出
TRISA1=1; //配置A1端口為輸入
SYNC=0; //EUSART選擇異步模式工作
BRGH=0; //選擇低頻傳送
TX9=0; //不發(fā)送第9位數(shù)據(jù)
RX9=0;//不接收第9位數(shù)據(jù)
TXEN=1; //串口發(fā)送功能打開(kāi)
CREN=1; //串口接收功能打開(kāi)
SPEN=1; //串口功能打開(kāi)
TXIE=0; //關(guān)閉發(fā)送中斷
RCIE=1;//打開(kāi)接收中斷
}
/*********************************************
AD轉(zhuǎn)換初始化函數(shù)
功能:將AD模塊初始化,本函數(shù)并未將AD模塊初始化為測(cè)量壓力還是溫度模式,選擇模式在ADModel_shift()函數(shù)中完成
*********************************************/
oid AD_init()
{
TRISC2=1; //配置RC2為輸出模式
ANSC2=1; //配置RC2為模擬量模式
INLVLC2=0; //配置RC2為T(mén)TL輸入方式
RC2=0;//配置RC2端口引腳電平小于VIL
ADCON1=0b10010000; //選擇AD轉(zhuǎn)換數(shù)據(jù)輸出格式為右對(duì)齊,使用FOCS/8時(shí)鐘作為AD轉(zhuǎn)換時(shí)鐘,選擇負(fù)向參考電壓為VSS,正向參考電壓為VDD
ADIF=0; //清零AD轉(zhuǎn)換中斷
ADIE=0;//關(guān)閉AD轉(zhuǎn)換中斷
}
/************************************************
函數(shù)名稱:ADModel_shift(int flag)
參數(shù):標(biāo)志量 int flag 0表示要將AD模塊轉(zhuǎn)換為測(cè)量壓力模式,1表示轉(zhuǎn)換為測(cè)量溫度模式
功能:將AD模塊在測(cè)量溫度和壓力之間進(jìn)行切換
************************************************/
void ADModel_shift(int flag)
{
if(flag==0) {
ADCON0=0b00011001;
//打開(kāi)通道6,并啟用AD模塊(本開(kāi)發(fā)板用的是8號(hào)管腳,對(duì)應(yīng)AD轉(zhuǎn)換通道六)
}
else
{
ADCON0=0b01110101; //測(cè)溫度并且使能AD模塊
TSEN =1; //打開(kāi)溫度傳感器功能
TSRNG=1; //溫度傳感器選擇高電壓模式
FVREN=1;//啟用參考電壓模塊
}
// delay(1000);//模式轉(zhuǎn)換完成后進(jìn)行必要的延時(shí)等待,這樣測(cè)量的結(jié)果才精準(zhǔn)
}
/**********************************************
DA初始化
**********************************************/
void DA_init()
{
DACCON0=0b11100000;//打開(kāi)DA模塊,將DA轉(zhuǎn)換的結(jié)果從DACOUT管腳輸出,選擇VDD提
供正向參考電壓,選擇VSS提供負(fù)向參考電壓
RA0=0;//配置A0端口引腳電平小于VIL
// TRISA0=0;//在串口配置中本管腳已經(jīng)配置為輸出模式,這里可以省略
}
/***************************************************
簡(jiǎn)單的延時(shí)函數(shù)
參數(shù):int time
****************************************************/
void delay(int time)
{
while(time--);
}
/****************************************************
程序總初始化函數(shù)
函數(shù)名:INIT()
返回值:無(wú)
功能:本函數(shù)實(shí)現(xiàn)對(duì)程序的總初始化,包括時(shí)鐘的初始化,端口的設(shè)置,串口的初始化,A/D模塊的初始化
*****************************************************/
void INIT()
{
/*時(shí)鐘初始化*/
OSCCON=0b01101010;//初始化振蕩器控制寄存器,選擇主頻4MHZ內(nèi)部時(shí)鐘
/*串口的初始化*/
USTRA_init();//執(zhí)行串口初始化函數(shù)
/*AD模塊的初始化*/
AD_init();
/*DA模塊的初始化*/
// DA_init();//不能再串口使用時(shí)使用DA,因?yàn)?者公用同一個(gè)端口
/*中斷的初始化*/
PEIE=1; //開(kāi)啟外設(shè)中斷
GIE=1;//開(kāi)啟全局中斷
}
/******************************************************
數(shù)據(jù)采集函數(shù)
函數(shù)名:Get_data()
返回值:無(wú)
功能:本函數(shù)實(shí)現(xiàn)一次性采集100組數(shù)據(jù),將其存儲(chǔ)在數(shù)組DATA[100][2]中,每組數(shù)據(jù)包含兩個(gè)量:當(dāng)前壓力的數(shù)字量和當(dāng)前溫度的數(shù)字量
*******************************************************/
void Get_data()
{
int i=0;
ADModel_shift(0);//將AD模塊調(diào)整為測(cè)量壓力模式
delay(1000);
for(i=0;i《=9;i++)
{
ADGO=1;//開(kāi)始AD轉(zhuǎn)換
while(ADGO==1); //等待結(jié)果轉(zhuǎn)換完成
DATA[i][0]=ADRESH;//將高8為結(jié)果存儲(chǔ)在壓力數(shù)據(jù)量低八位位置
delay(1000);//延時(shí)等待
DATA[i][0]=DATA[i][0]《《8; //將壓力數(shù)據(jù)量的高八位左移8位
DATA[i][0]=ADRESL; //將低8位結(jié)果存儲(chǔ)在壓力數(shù)據(jù)量低八位位置
delay(1000);
ADIF=0;
//AD轉(zhuǎn)換完成中斷標(biāo)志軟件清零
}
ADModel_shift(1);//將AD模塊調(diào)整為測(cè)量溫度模式
delay(1000);
for(i=0;i《=9;i++)
{
ADGO=1;//開(kāi)始AD轉(zhuǎn)換
while(ADGO==1); //等待結(jié)果轉(zhuǎn)換完成
DATA[i][1]=ADRESH;//將高8為結(jié)果存儲(chǔ)在壓力數(shù)據(jù)量低八位位置
delay(1000);//延時(shí)等待
DATA[i][1]=DATA[i][0]《《8; //將壓力數(shù)據(jù)量的高八位左移8位
DATA[i][1]=ADRESL; //將低8位結(jié)果存儲(chǔ)在壓力數(shù)據(jù)量低八位位置
delay(1000);
ADIF=0;
//AD轉(zhuǎn)換完成中斷標(biāo)志軟件清零
}
}
/************************************* 串口發(fā)送函數(shù)
函數(shù)名:USTRA_Send()
參數(shù):無(wú)
功能:本函數(shù)實(shí)現(xiàn)將AD轉(zhuǎn)換完成的數(shù)據(jù)通過(guò)串口發(fā)送出去,函數(shù)執(zhí)行一次,連發(fā)五個(gè)壓力數(shù)據(jù)量再發(fā)五個(gè)溫度數(shù)據(jù)量,開(kāi)始發(fā)送時(shí)都發(fā)送一個(gè)0A01
*************************************/
void USTRA_Send()
{
int i =0;
TXREG=‘A’; //開(kāi)始發(fā)送時(shí)先發(fā)送一個(gè)0A01 while(TRMT==0);
TXREG=‘1’;
while(TRMT==0);
ADModel_shift(0);//將AD模塊調(diào)整為測(cè)量壓力模式
delay(1000);
for(i=0;i《=4;i++)//連發(fā)五個(gè)壓力數(shù)據(jù)量
{ ADGO=1;//開(kāi)始AD轉(zhuǎn)換
while(ADGO==1);//等待結(jié)果轉(zhuǎn)換完成
TXREG=ADRESH;
while(TRMT==0); 10
TXREG=ADRESL;
while(TRMT==0);
ADIF=0;//AD轉(zhuǎn)換完成中斷標(biāo)志軟件清零
}
ADModel_shift(1);//將AD模塊調(diào)整為測(cè)量溫度模式
delay(1000);
for(i=0;i《=4;i++)//連發(fā)五個(gè)溫度數(shù)據(jù)量
{
ADGO=1;//開(kāi)始AD轉(zhuǎn)換
while(ADGO==1);//等待結(jié)果轉(zhuǎn)換完成
TXREG=ADRESH;
while(TRMT==0);
TXREG=ADRESL; 25
while(TRMT==0);
ADIF=0;//AD轉(zhuǎn)換完成中斷標(biāo)志軟件清零
}
}
/*****************************************
EEPROM寫(xiě)函數(shù)
******************************************/ 35
void EEPROM_write(int add,int data)
{
int k=0;
WREN=1;//打開(kāi)寫(xiě)功能
EEADRL=add; //說(shuō)明存儲(chǔ)地址地址
EEDATL=data;//寫(xiě)1
EECON2=0x55;
EECON2=0xAA;
WR=1;
k=500;
while(k--);
WREN=0;//關(guān)閉寫(xiě)功能
}
/**********************************************
EEPROM讀函數(shù)
***********************************************/
char EEPROM_Read(int add)
{ int k=0;
char a=0;
EEADRL=add;//說(shuō)明存儲(chǔ)地址
EEPGD=0;
CFGS=0;
RD=1;
k=500;
while(k--);
a=EEDATL;
return a;//返回讀取的結(jié)果
}
/**********************************************
功能:串口接收中斷服務(wù)函數(shù)
**********************************************/
interrupt ISR(void)
{
USTRA_init();
GIE=0;//關(guān)閉全局中斷
char temp=0; //存放接收到的數(shù)據(jù)的緩存
int flag=0;
//表示本次接收到的數(shù)據(jù)是否為各個(gè)系數(shù)開(kāi)頭的標(biāo)志量,1表示為標(biāo)志量,0表示不為標(biāo)志量,即數(shù)據(jù),若為標(biāo)志量,則表示上一個(gè)系數(shù)接收完畢,需要將其存儲(chǔ),否則則繼續(xù)接收
int i=0,j=0; 30
if(FLAG_receivefactor==0)
//接收系數(shù)標(biāo)志位,為1,表示本單片機(jī)已經(jīng)被選中,并且被要求開(kāi)始接收系數(shù),為0表示本次單片機(jī)還未被選中
{
temp=RCREG; 35
if(temp==‘A’)
//若接收到的數(shù)據(jù)位A,表示要求本單片機(jī)發(fā)送采集的數(shù)據(jù)
USTRA_Send();
else if(temp==‘B’)
//若接收到的數(shù)據(jù)位B,表示上位機(jī)選中本單片機(jī),要求接收系數(shù)
{
FLAG_receivefactor=1;
TXREG=‘N’;
}
}
else
//接收系數(shù)標(biāo)志位,為1,表示本單片機(jī)已經(jīng)被選中,被要求接收系數(shù)
{
temp=RCREG;
TXREG=temp;
while(TRMT==0);
switch(temp)
{
case ‘a(chǎn)’: Factor_number=0;
//表示下次發(fā)送的是系數(shù)1,系數(shù)1是第一個(gè)系數(shù),所以沒(méi)有前面的系數(shù)可以保存,所以Flag應(yīng)該為1
flag=0;
break;
case ‘b’: Factor_number=1;
flag=1;
break;
case ‘c’: Factor_number=2;
flag=1;
break;
case ‘d’: Factor_number=3;
flag=1;
break;
case ‘e’: Factor_number=4;
flag=1;
break;
case ‘f’: Factor_number=5;
flag=1;
break;
case ‘g’: Factor_number=6;
flag=1;
break;
case ‘h’: Factor_number=7;
flag=1;
break;
case ‘i’: Factor_number=8;
flag=1;
break;
case ‘j’: Factor_number=9;
flag=1;
break;
case ‘k’: Factor_number=10;
flag=1;
break;
case ‘l’: Factor_number=11;
flag=1;
break;
case ‘m’: Factor_number=12;
flag=1;
break;
case ‘n’: Factor_number=13;
flag=1;
break;
case ‘o’: Factor_number=14;
flag=1;
break;
case ‘p’: Factor_number=15;
flag=1; break; case ‘q’: Factor_number=16;
flag=1;
break;
default:flag=0;
//該標(biāo)志量表示本次接收中斷傳來(lái)的系數(shù)是否是標(biāo)志量,0表示是數(shù)據(jù),1表示就是標(biāo)志量
}
if(flag==0&&temp!=‘a(chǎn)’)
//若此次中斷未接收到標(biāo)志量,或者接收到第一個(gè)系數(shù)的標(biāo)志量即a,則不用將前面接收到的系數(shù)保存 10
{
real =real*10+(temp-48);
}
else
//若此次中斷接收到標(biāo)志量,則表示上一個(gè)系數(shù)傳送完畢,對(duì)其進(jìn)行存儲(chǔ) 15
{
xishu1[Factor_number]=real;
//更新xishu1中相應(yīng)系數(shù)的值
for(i=7,j=1;i》=0&&j《=8;i--,j++)
{
EEPROM_write((Factor_number-1)*8+j,real》》(8*i));
//將新的系數(shù)重新保存在EEPROM中,大端存儲(chǔ)
TXREG=EEPROM_Read((Factor_number-1)*8+j);
while(TRMT==0);
}
real=0; //real清零
flag=0;//flag清零
if(Factor_number==16)
//如果最后一個(gè)系數(shù)接收完畢,則將FLAG_receivefactor標(biāo)志量清零
{
FLAG_receivefactor=0;
}
}
}
GIE=1;//打開(kāi)總中斷
}
main()
{
int i=0,j=0;
long long int xishu2[4]={0};
long long long int result=0; long long int temp=0;
INIT();
for(i=0;i《=15;i++)
for(j=1;j《=8;j++)
{
xishu1[i]=EEPROM_Read((i*8)+j);//將系數(shù)從EEPROM中取出
TXREG=xishu1[i];
delay(1000);
if(j!=8)
xishu1[i]=xishu1[i]《《8;
}
TXREG=‘a(chǎn)’;
while(1)
{
int TEM=0,PRESS=0;
ADModel_shift(0);
//將AD模塊調(diào)整為測(cè)量壓力模式
delay(1000);
ADGO=1;//開(kāi)始AD轉(zhuǎn)換
while(ADGO==1);//等待結(jié)果轉(zhuǎn)換完成
PRESS=ADRESH;
PRESS=TEM《《8; 20
// while(TRMT==0);
PRESS=PRESS+ADRESL;
//while(TRMT==0);
ADIF=0;//AD轉(zhuǎn)換完成中斷標(biāo)志軟件清零
ADModel_shift(1);//將AD模塊調(diào)整為測(cè)量溫度模式
delay(1000);
ADGO=1;//開(kāi)始AD轉(zhuǎn)換
while(ADGO==1);//等待結(jié)果轉(zhuǎn)換完成
TEM=ADRESH; TEM=PRESS《《8;
//while(TRMT==0);
TEM=TEM+ADRESL;
// while(TRMT==0);
ADIF=0;//AD轉(zhuǎn)換完成中斷標(biāo)志軟件清零
}
TXREG=‘a(chǎn)’;//沒(méi)法送完依次結(jié)果,就發(fā)送一個(gè)‘a(chǎn)’
while(TRMT==0);
}
}
評(píng)論