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; //中断使能
qq攻防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(SS
PIF==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();
}
}