⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pic18 单片机学习(程序实例).txt

📁 18F基本模块初始化程序均在内
💻 TXT
字号:
PIC18 单片机学习(程序实例)

说明:

18F基本模块初始化程序均在内,且测试通过,主程序可以调用各个程序!

编译器使用PICC18

//程序主要用于18F单片机学习
#include <pic18.h>    //18系列单片机头文件
//-------------函数定义--------------
void delay(unsigned int rr);
void timer1(void);
void SPI_Iint(void);  //串行SPI输出设置函数
void display(void);
void i2cint(void);    //i2c总线初始化程序
void c64R(void);      //i2c接口的EEPROM存储器(读程序)
void c64W(void);      //写程序
void Start(void);     //起始位发送函数
void Stop(void);      //停止位发送函数
void WriteWait(void); //等待函数
void Senddata(unsigned char data); //数据发送函数
void Restart(void);   //重复启动函数
void Datain(void);    //数据读入
void Uartint(void);   //通用同步/异步收发器初始化程序
void Udatas(unsigned char dad); //UART数据发送
void Uartrs(void);    //串口接收数据发送函数
void ADint(void);     //AD模块初始化
void shuchai(void);
//-----------数据寄存器定义----------
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;          //定时器0,中断计数寄存器
unsigned char save;
unsigned char conet;
unsigned char *Counter;    //接收数据指针
unsigned char DADh;        //AD缓存,
unsigned char DADl;
unsigned int  Dat;  
unsigned int  Dat1;        //保存上次的AD转换值,用于比  
 
volatile bit  DADflage;    //AD转换标志 
volatile bit  I2Cerror;    //I2C错误标志
volatile bit  Uartsend;    //异步串口数据发送允许
union                      //联合体用来对C64的地址进行操作!
{
  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看门狗是可以用软件控制开启的!
  INTCON=0;
  ADCON1=0x07;               //AD端口全部始能为数字IO口
  TRISB7=0;                  //设置为输出端口
  RB7=0;  
  PIE1=0;
  PIE2=0;
  PIE3=0;
  buf[0]=0;
  buf[1]=0;
  buf[2]=0;
  buf[3]=0;
  //CMCON=0x07;              //关闭比较器,18F2680没有比较器
}
//***********************************
//高优先级中断函数
//***********************************
void interrupt HI_ISR()
{
  if(TMR0IF&TMR0IE)          //确认是定时器0中断
  { 
    dd++;
    TMR0IF=0; 
    TMR0H=0xd8;              //10ms定时常数
    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转换中断
 {   
   ADIF=0;       //清0
   DADh=ADRESH;
   DADl=ADRESL;
   Dat=256*DADh+DADl;
   if(((Dat-Dat1)==1)||((Dat1-Dat)==1))
   {
     Dat=Dat1;
   }
   DADflage=1;
 } 
}  
   
//***********************************
//低优先级中断函数
//***********************************
void interrupt low_priority LOW_ISR()
{
  if(RCIF&RCIE)    //如果是串口接收中断的话,则进入中断处理
  {
    RCIF=0;        //清中断标志 
    *Counter=RCREG;//读取数据到数组
    Counter++;
    if((Counter-&receive[0])==10)
    {
      Counter=&receive[0];
      Uartsend=1;
    }
  } 
}
//***********************************
//定时器0初始化子程序
//***********************************
void timer1()
{ 
  IPEN=1;           //打开高低优先级
  T0CON=0x09;       //把定时器0设定为16位定时器,内部时钟触发,不使用分频器
  TMR0IE=1;         //允许定时器0溢出中断
  TMR0IF=0;         //清除中断标志
  TMR0IP=1;         //设定定时器0中断为高优先级
  TMR0H=0xD8;       //定时常数
  TMR0L=0xef;
  GIE=1;
  PEIE=1;
  TMR0ON=1;
}
//***********************************
//AD转换初始化函数
//***********************************
void ADint()    //使用于18F2680!
{               
  ADCON0=0x01;  //AD转换速率为Fosc/4,并使能AD转换模块
  ADCON1=0x0e;  //选择为右对齐模式,并且使能AD0为模拟通道
  ADCON2=0x91;
  TRISA=1;      //RA0为输入模式
  ADIF=0;       
  ADIE=1;       //中断使能
  IPEN=1;       //使能高低中断优先级
  ADIP=1;       //AD转换设置为高优先级中断
  GIE=1;        //开总中断以及外部中断
  PEIE=1;     
  DADflage=0;  
}               
//***********************************
//I2C初始化函数
//***********************************
void i2cint()
{
  SSPCON1=0x08;             //允许串口工作,I2C主控方式,时钟=Fosc/[4*(SSPADD+1)]
  RC4=1;                    //设置为输入
  RC3=1;
  SSPADD=7;                 //时钟频率约为0.125M
  SSPSTAT=0x80;             //关闭标准速度方式
  SSPCON2=0;
  SSPEN=1;                  //使能串口(SSP模块)
  I2Cerror=0;
}
//***********************************
//SPI初始化程序
//***********************************
void SPI_Iint()
{
  TRISC5=0;          //SDO引脚
  TRISC4=1;          //SDI引脚
  TRISC3=0;          //SCK,串行时钟输出引脚
  TRISA5=0;          //RA5为从动SS端
  SSPCON1=0x30;      //使能串口,高电平为空闲状态,并且发送频率为fose/4,主控方式;
  SSPSTAT=0xc0;      //时钟下降沿发送数据!
  SSPIF=0;  
  conet=0;  
}
//***********************************
//通用同步/异步收发器(UART)初始化
//***********************************
void Uartint()
{
  TXSTA=0x04;       //设置为高速异步,方式
  RCSTA=0x80;       //使能UART
  TRISC6=0;         //设置为输入,对外部呈现高阻态
  TRISC7=1;
  SPBRG=25;         //设置波特率为9600  
                    //波特率计算公式
                    //1.同步方式:波特率=Fosc/[4(X+1)]
                    //2.异步方式:BRGH=0:波特率=Fosc/[64(x+1)]
                    //            BRGH=1:波特率=Fosc/[16(x+1)]
  IPEN=1;           //开中断优先级
  RCIP=0;           //串口接收使能为低优先级
  RCIE=1;           //串口接收中断使能
  RCIF=0;
  TXIE=0;           //禁止发送中断
  GIE=1;            //开总中断和外围中断
  PEIE=1;         
  TXEN=1;           //使能串口发送
  CREN=1;           //使能串口接收 ,注意18F是CREN而不是RCEN,编译器都认为是正确的但是RCEN不管用!
  Counter=&receive[0];//把数组的首地址给指针
  Uartsend=0;
} 
//***********************************
//AD转换函数
//***********************************
void ADchange()
{
  ADCON0=ADCON0|0x02;  //启动AD转换
  if(DADflage)         //如果AD转换完成,这里采用
  {
    DADflage=0;
    shuchai();
    display();
  }
}
//***********************************
//AD 数据拆分
//***********************************
void shuchai()
{
  unsigned int i;
  Dat1=Dat;      //保存这次的计数值
  i=Dat;
  buf[3]=i/1000; //取出千位
  i=i%1000;      //取出百位数
  buf[2]=i/100;  //取出百位数
  i=i%100;       //取出十位数
  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 数据发送子程序
//***********************************
void Udatas(unsigned char dad)
{
  TXREG=dad;
  while(1)
  {
    if(TXIF==1) break;   //等待数据写入
  }
  delay(80);
}                  
//***********************************
//I2C写子程序
//***********************************
void c64W()
{
  Start();
  if(I2Cerror==1)
  {
    I2Cerror=0;
    return;         //返回防止死循环
  }
  Senddata(0xa0);   //发送寻址地址,以及写操作地址!
  if(I2Cerror==1)
  {
    I2Cerror=0;
    Stop();         //错误处理
    return;         //返回防止死循环
  }
  Senddata(0x00);   //发送高位地址
  if(I2Cerror==1)
  {
    I2Cerror=0;
    Stop();         //错误处理
    return;         //返回防止死循环
  }
  Senddata(0x40);   //发送地址低字节
  if(I2Cerror==1)
  {
    I2Cerror=0;
    Stop();         //错误处理
    return;         //返回防止死循环
  }
 Senddata(0x55);    //发送数据 
 if(I2Cerror==1)
  {
    I2Cerror=0;
    Stop();         //错误处理
    return;         //返回防止死循环
  }
 Stop();
   
}
//***********************************
//I2C读数据程序
//***********************************
void c64R()
{
  Start();
  if(I2Cerror==1)
  {
    I2Cerror=0;
    return;         //返回防止死循环
  }
  Senddata(0xa0);   //发送寻址地址,以及写操作地址!
  if(I2Cerror==1)
  {
    I2Cerror=0;
    Stop();         //错误处理
    return;         //返回防止死循环
  }
  Senddata(0x00);   //发送高位地址
  if(I2Cerror==1)
  {
    I2Cerror=0;
    Stop();         //错误处理
    return;         //返回防止死循环
  }
  Senddata(0x40);   //发送地址低字节
  if(I2Cerror==1)
  {
    I2Cerror=0;
    Stop();         //错误处理
    return;         //返回防止死循环
  }

 Restart();         //发送重新起始位
 Senddata(0xa1);    //发送读命令
 if(I2Cerror==1)
 {
   I2Cerror=0;
   Stop();         //错误处理
   return;         //返回防止死循环
 }
 Datain();
 Stop();
 
 if(save==0x55)
 {
   RB7=1;
 }
 conet++;
}
//***********************************
//I2C重复启动
//***********************************
void Restart()
{
  RSEN=1;
  while(1)
  {
    if(SSPIF==1) break;
  }
  SSPIF=0;
}
//***********************************
//I2C数据写等待
//***********************************
void WriteWait()
{
  while(1)
  {
   Start();           //在数据写入时间,如果在给器件发送数据不会有响应
   Senddata(0xa0);
   Stop();
   if(I2Cerror==0) break; //等待数据写入,=0则有应答位产生
  }
}
//***********************************
//I2C起始位发送函数
//***********************************
void Start()
{
  unsigned char i=0;
  SEN=1;            //起始位发送
  while(1)
  {
    i++;
    if(SSPIF==1) break;
    if(i==200)      //防止死循环
    {
      i=0;
      I2Cerror=1;   
      break;  
    }
  }
  SSPIF=0;
}
//***********************************
//I2C停止位发送
//***********************************
void Stop()
{
  PEN=1;
  while(1)
  {
    if(SSPIF==1) break;
  }
  SSPIF=0;
}
//***********************************
//I2C数据发送函数
//***********************************
void Senddata(unsigned char data)
{
  unsigned char i;
  SSPBUF=data;            //发送数据
  while(1)
  {
    if(SSPIF==1) break;
  }
  SSPIF=0;
  for(i=0;i<10;i++)
  {}
  if(ACKSTAT)   //如果没有发出应答信号
  {
    I2Cerror=1;
  }
  else          //如果发出应答信号
  {
    I2Cerror=0;
  }
}
//***********************************
//I2C 数据读入函数
//***********************************
void Datain()
{
  RCEN=1;
  while(1)
  {
    if(SSPIF==1) break;
  }
  SSPIF=0;
  save=SSPBUF;      //读数
  ACKDT=1;          //发送非应答位
  ACKEN=1;
  while(1)
  {
   if(SSPIF==1) break;
  }
  SSPIF=0;
}
//***********************************
//164显示程序
//***********************************
void display()         //164显示程序,用SPI端口发送数据
{
  unsigned char i;
  unsigned char y,t;   //传输完四个字节
  for(i=0;i<4;i++)
  {
    y=buf[i];
    t=table[y];
    SSPBUF=t; 
    while(1)
    {
     if(SSPIF) break;
    }
    SSPIF=0; 
  }       
}         
//***********************************
//延时函数
//***********************************
void delay(unsigned int rr)  //延时函数
{         
  unsigned int asd;
  for(asd=0;asd<rr;asd++)
  {}      
}         
//***********************************
//主函数  
//***********************************
void  main()
{          
  PICint();          //初始化函数
//Uartint();         //异步串行口初始化
//SPI_Iint();
//ADint();           //AD模块初始化
//timer1();   
//display();
//i2cint();          //I2C初始化
//c64W();            //往C64里写一次数据
//WriteWait();
//c64R();            //读C64里
  while(1) 
  {        
    //CLRWDT();
    //delay(20000);
    CLRWDT();
    RB7=1;
    CLRWDT();
    SLEEP();         //等待看门狗复位
    RB7=0;
    delay(20000);
    CLRWDT();   
  }       
}         

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -