pic16f1824代码例程

嵌入式设计应用

128人已加入

描述

  例程的作用类似于函数,但含义更为丰富一些。例程是某个系统对外提供的功能接口或服务的集合。比如操作系统的API、服务等就是例程;Delphi或C++Builder提供的标准函数和库函数等也是例程。我们编写一个DLL的时候,里面的输出函数就是这个DLL的例程。

  可以这么简单地来理解:把一段相对独立的代码写成单独的一个模块就是函数的概念。我们可以在自己的程序中编写很多个函数,从而实现模块化编程。但这些模块或者说函数并不一定向外输出(即提供给别的程序使用),只用于当前这个程序里面。此时这些函数就仅仅具有独立函数的意义,但不是例程。

  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}; //用于存储上位机发来的16个系数

  bit FLAG_receivefactor=0; //接收标志位,如果为一表示本次中断需要接收系数

  int Factor_number=-1;//系数编号,表示本次中断接收的是第几个编号的系数

  long long int real=0;

  /****************************************** 串口初始化函数

  ******************************************/

  void USTRA_init()

  {

  BRG16=0;//使用8位波特率发生器

  SPBRGL=12;//设置波特率发生寄存器的值4800

  20SPBRGH=0;

  ANSA1=0; //A1引脚被配置为端口或数字特殊功能

  ANSA0=0;//A0引脚被配置为端口或数字特殊功能

  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; //不发送第9位数据

  RX9=0;//不接收第9位数据

  TXEN=1; //串口发送功能打开

  CREN=1; //串口接收功能打开

  SPEN=1; //串口功能打开

  TXIE=0; //关闭发送中断

  RCIE=1;//打开接收中断

  }

  /*********************************************

  AD转换初始化函数

  功能:将AD模块初始化,本函数并未将AD模块初始化为测量压力还是温度模式,选择模式在ADModel_shift()函数中完成

  *********************************************/

  oid AD_init()

  {

  TRISC2=1; //配置RC2为输出模式

  ANSC2=1; //配置RC2为模拟量模式

  INLVLC2=0; //配置RC2为TTL输入方式

  RC2=0;//配置RC2端口引脚电平小于VIL

  ADCON1=0b10010000; //选择AD转换数据输出格式为右对齐,使用FOCS/8时钟作为AD转换时钟,选择负向参考电压为VSS,正向参考电压为VDD

  ADIF=0; //清零AD转换中断

  ADIE=0;//关闭AD转换中断

  }

  /************************************************

  函数名称:ADModel_shift(int flag)

  参数:标志量 int flag 0表示要将AD模块转换为测量压力模式,1表示转换为测量温度模式

  功能:将AD模块在测量温度和压力之间进行切换

  ************************************************/

  void ADModel_shift(int flag)

  {

  if(flag==0) {

  ADCON0=0b00011001;

  //打开通道6,并启用AD模块(本开发板用的是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;//在串口配置中本管脚已经配置为输出模式,这里可以省略

  }

  /***************************************************

  简单的延时函数

  参数:int time

  ****************************************************/

  void delay(int time)

  {

  while(time--);

  }

  /****************************************************

  程序总初始化函数

  函数名:INIT()

  返回值:无

  功能:本函数实现对程序的总初始化,包括时钟的初始化,端口的设置,串口的初始化,A/D模块的初始化

  *****************************************************/

  void INIT()

  {

  /*时钟初始化*/

  OSCCON=0b01101010;//初始化振荡器控制寄存器,选择主频4MHZ内部时钟

  /*串口的初始化*/

  USTRA_init();//执行串口初始化函数

  /*AD模块的初始化*/

  AD_init();

  /*DA模块的初始化*/

  // DA_init();//不能再串口使用时使用DA,因为2者公用同一个端口

  /*中断的初始化*/

  PEIE=1; //开启外设中断

  GIE=1;//开启全局中断

  }

  /******************************************************

  数据采集函数

  函数名:Get_data()

  返回值:无

  功能:本函数实现一次性采集100组数据,将其存储在数组DATA[100][2]中,每组数据包含两个量:当前压力的数字量和当前温度的数字量

  *******************************************************/

  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为结果存储在压力数据量低八位位置

  delay(1000);//延时等待

  DATA[i][0]=DATA[i][0]《《8; //将压力数据量的高八位左移8位

  DATA[i][0]=ADRESL; //将低8位结果存储在压力数据量低八位位置

  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为结果存储在压力数据量低八位位置

  delay(1000);//延时等待

  DATA[i][1]=DATA[i][0]《《8; //将压力数据量的高八位左移8位

  DATA[i][1]=ADRESL; //将低8位结果存储在压力数据量低八位位置

  delay(1000);

  ADIF=0;

  //AD转换完成中断标志软件清零

  }

  }

  /************************************* 串口发送函数

  函数名:USTRA_Send()

  参数:无

  功能:本函数实现将AD转换完成的数据通过串口发送出去,函数执行一次,连发五个压力数据量再发五个温度数据量,开始发送时都发送一个0A01

  *************************************/

  void USTRA_Send()

  {

  int i =0;

  TXREG=‘A’; //开始发送时先发送一个0A01 while(TRMT==0);

  TXREG=‘1’;

  while(TRMT==0);

  ADModel_shift(0);//将AD模块调整为测量压力模式

  delay(1000);

  for(i=0;i《=4;i++)//连发五个压力数据量

  { 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++)//连发五个温度数据量

  {

  ADGO=1;//开始AD转换

  while(ADGO==1);//等待结果转换完成

  TXREG=ADRESH;

  while(TRMT==0);

  TXREG=ADRESL; 25

  while(TRMT==0);

  ADIF=0;//AD转换完成中断标志软件清零

  }

  }

  /*****************************************

  EEPROM写函数

  ******************************************/ 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读函数

  ***********************************************/

  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;//返回读取的结果

  }

  /**********************************************

  功能:串口接收中断服务函数

  **********************************************/

  interrupt ISR(void)

  {

  USTRA_init();

  GIE=0;//关闭全局中断

  char temp=0; //存放接收到的数据的缓存

  int flag=0;

  //表示本次接收到的数据是否为各个系数开头的标志量,1表示为标志量,0表示不为标志量,即数据,若为标志量,则表示上一个系数接收完毕,需要将其存储,否则则继续接收

  int i=0,j=0; 30

  if(FLAG_receivefactor==0)

  //接收系数标志位,为1,表示本单片机已经被选中,并且被要求开始接收系数,为0表示本次单片机还未被选中

  {

  temp=RCREG; 35

  if(temp==‘A’)

  //若接收到的数据位A,表示要求本单片机发送采集的数据

  USTRA_Send();

  else if(temp==‘B’)

  //若接收到的数据位B,表示上位机选中本单片机,要求接收系数

  {

  FLAG_receivefactor=1;

  TXREG=‘N’;

  }

  }

  else

  //接收系数标志位,为1,表示本单片机已经被选中,被要求接收系数

  {

  temp=RCREG;

  TXREG=temp;

  while(TRMT==0);

  switch(temp)

  {

  case ‘a’: Factor_number=0;

  //表示下次发送的是系数1,系数1是第一个系数,所以没有前面的系数可以保存,所以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;

  //该标志量表示本次接收中断传来的系数是否是标志量,0表示是数据,1表示就是标志量

  }

  if(flag==0&&temp!=‘a’)

  //若此次中断未接收到标志量,或者接收到第一个系数的标志量即a,则不用将前面接收到的系数保存 10

  {

  real =real*10+(temp-48);

  }

  else

  //若此次中断接收到标志量,则表示上一个系数传送完毕,对其进行存储 15

  {

  xishu1[Factor_number]=real;

  //更新xishu1中相应系数的值

  for(i=7,j=1;i》=0&&j《=8;i--,j++)

  {

  EEPROM_write((Factor_number-1)*8+j,real》》(8*i));

  //将新的系数重新保存在EEPROM中,大端存储

  TXREG=EEPROM_Read((Factor_number-1)*8+j);

  while(TRMT==0);

  }

  real=0; //real清零

  flag=0;//flag清零

  if(Factor_number==16)

  //如果最后一个系数接收完毕,则将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);//将系数从EEPROM中取出

  TXREG=xishu1[i];

  delay(1000);

  if(j!=8)

  xishu1[i]=xishu1[i]《《8;

  }

  TXREG=‘a’;

  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’;//没法送完依次结果,就发送一个‘a’

  while(TRMT==0);

  }

  }

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分