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