PIC单片机C语言之PIC16F887(4MhZ晶振)
一、端口的定义与while(1)的使用
#include "pic.h"
#define uchar unsigned char//宏定义
#define uint unsigned int//宏定义
__CONFIG(0x3B31);//定义配置字
void delay();//延时子函数
void main()
{
TRISA=0x00;
ADCON1=0xf7; //将PORTA和PORTE口作为IO用
PORTA=0x00;
while(1)
{
RA5=1;//AN功能口电平不能改变
delay();
RA5=0;
delay();
}
}
void delay()
{
uint a;//定义局部变量
for(a=10;a>0;a--){ }
}
//PORTA和PORTE口作为IO用的定义
//While(1)在这里作为一个大循环用,如果后面加“;”号,则程序将停在While(1)不往下执行。
-----------------------------------------------------------------------------------------------------------------
二、延时
1、通过语句延时程序(带参数)
#include "pic.h"
#define uchar unsigned char//宏定义
#define uint unsigned int//宏定义
__CONFIG(0x3B31);//定义配置字
void delay(uint x);//声明子函数
void main()
{
TRISD2=0;
while(1)
{
RD2=1;
delay(5);//可以改变程序延时时间,当前5.04mS
RD2=0;
delay(5);//可以改变程序延时时间,当前5.04mS
}
}
void delay(uint x)//4M晶振
{
uint a,b;
for(a=x;a>0;a--)//完整嵌套如下
{
for(b=110;b>0;b--)
{
};//分号加亦可,不加亦可
};//分号加亦可,不加亦可
}
//在延时程序的前后两个地方设置断点(Breakpoints),再打开Stopwatch,然后全速运行两次
-----------------------------------------------------------
2、通过语句延时程序(不带参数)
#include "pic.h"
#define uchar unsigned char//宏定义
#define uint unsigned int//宏定义
__CONFIG(0x3B31);//定义配置字
void delay();//声明子函数
void main()
{
TRISD2=0;
while(1)
{
RD2=1;
delay();//延时1.05mS
RD2=0;
delay();//延时1.05mS
}
}
void delay()//4M晶振
{
uint a,b;
for(a=10;a>0;a--)//for嵌套
for(b=10;b>0;b--);
}
//在延时程序的前后两个地方设置断点(Breakpoints),再打开Stopwatch,然后全速运行两次
-----------------------------------------------------------
3、C程序延时时间计算
void delay()
{
uint i;
for(i=0;i<20000;i++);
}
我们怎么来算呢,先将20000转成16进制,得到4E20,然后将高字节4E乘以6得到十进制468,再将468+2=470,然后将十进制470*十六进制20(即十进制32)=15040;所心这个延时函数总共要执行15040个周期,假设所用的晶振为12MHZ,则该段函数总延时:15.04ms。
有了这个公式我们如果想要设定指定的延时长度就可以用它的己知公式确定。即:总时间=[(6*i值的高8位)+2]*i的低8位。
例如:设要延时125ms。
我们将低字节先赋值十进制200*(即:C8),然后再算高低节的定值,由式中可知125ms=200*((i值的高字节*6)+2),又可推算出(高低节*6)+2的总延迟时间应等于625us,将625/6=104.1666,取整数得到104,将104转成16进制得到68H,再将高字节和低字节组合起来即得到了定值,即:十六进制68C8,代入函数即如下:
void delay()
{
uint i;
for(i=0;i<0x68C8;i++);
}
如果写十进制就要将68C8转成10进制,即:26824,代入后得到:
void delay()
{
uint i;
for(i=0;i<26824;i++);
}
-----------------------------------------------------------
4、keil时间调试
第一步:选择单片机晶振
第二步:全编译
第三步:按d进入软件调试
第四步:进入程序设置两个断点:
第五步:按全速运行至第一个断点:注意时间是0.000389s
第六步:再按一次全速运行至第二个断点:注意时间是1.013412s
-----------------------------------------------------------------------------------------------------------------
三、外设
1、单按键检测与蜂鸣器发声(可控制发几声)
#include "pic.h"
#define uchar unsigned char//宏定义
#define uint unsigned int//宏定义
__CONFIG(0x3B31);//定义配置字
/
void Buzz(uchar num);//蜂鸣器发声子函数
void delay(uint x);//延时子函数
void scan();//按键扫描子函数
/
void main()
{
TRISB=0xff;
TRISE0=0;
RE0=0;
while(1)
{
scan();//扫描按键蜂鸣器发声
}
}
/
void scan()
{
if(RB0==0)
{
delay(10);
if(RB0==0)
{
while(!RB0)
{
Buzz(2);//发两声
}
}
}
}
/
void Buzz(uchar num)
{
uchar Buzz_num;
for(Buzz_num=num;Buzz_num>0;Buzz_num--)
{
RE0=1;
delay(50);
RE0=0;
delay(20);
}
}
/
void delay(uint x)//4M晶振
{
uint a,b;
for(a=x;a>0;a--)//完整嵌套如下
{
for(b=110;b>0;b--)
{
};//分号加亦可,不加亦可
};//分号加亦可,不加亦可
}
-----------------------------------------------------------
2、I2C端口模拟
#include "pic.h"
#define uchar unsigned char//宏定义
#define uint unsigned int//宏定义
__CONFIG(0x3B31);//定义配置字
uchar a;
#define sda RC1
#define scl RC2
子函数声明
void start(); //开始信号
void stop(); //停止
void respons(); //应答
void init();
void write_byte(uchar date); //写一个字节
uchar read_byte(); //读一个字节
void write_add(uchar address,uchar date); //写任意字节
uchar read_add(uchar address); //读任意字节
void delay();
void delay1(uchar x);
主函数
void main()
{
init();
write_add(23,0xaa);
delay1(100);
PORTB=read_add(23);
while(1);
}
void start() //开始信号
{
TRISC=0x00;
TRISB=0x00;
sda=1;
delay();
scl=1;
delay();
sda=0;
delay();
}
void stop() //停止
{
sda=0;
delay();
scl=1;
delay();
sda=1;
delay();
}
void respons() //应答
{
uchar i;
scl=1;
delay();
while((sda==1)&&(i<250))i++; //防止死循环
scl=0;
delay();
}
void init()
{
sda=1;
delay();
scl=1;
delay();
}
void write_byte(uchar date)
{
uchar bit_count;
for (bit_count=0;bit_count<8;bit_count++)
{
if ((date<<bit_count)&0x80) {sda=1;}
delay();
scl=1;
delay();
scl=0;
}
delay();
sda=1;
delay();
}
uchar read_byte()
{
uchar i,k;
scl=0;
delay();
sda=1;
delay();
for(i=0;i<8;i++)
{
scl=1;
delay();
k=(k<<1)|sda;
scl=0;
delay();
}
return k; //带返回值
}
void write_add(uchar address,uchar date)
{
start();
write_byte(0xa0); //器件地址 写操作
respons();
write_byte(address); //要写数据的地址
respons();
write_byte(date); //要写的数据
respons();
stop();
}
uchar read_add(uchar address)
{
uchar date;
start();
write_byte(0xa0); //器件地址 写操作
respons();
write_byte(address); //要写数据的地址
respons();
start();
write_byte(0xa1); //器件地址 读操作
respons();
date=read_byte(); //读一个字节放入date
stop();
return date;
}
void delay()
{ ;; }
void delay1(uchar x)
{
uchar a,b;
for(a=x;a>0;a--)
for(b=100;b>0;b--);
}
-----------------------------------------------------------
3、DS18B20数字温度传感器(数码管显示)
#include "pic.h"
#define uchar unsigned char
#define uint unsigned int
#define DQ RC1 //定义一个端口
#define DQ_HIGH() TRISC1=1
#define DQ_LOW() TRISC1=0;DQ=0
__CONFIG(0x3B31);
const uchar table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f};
const uchar table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,
0x87,0xff,0xef};
uint temper;
uchar a1,a2,a3,a4;
void delay(uint x);
void delayus(uint,uchar);
void init();
void disp(uchar num1,uchar num2,uchar num3,uchar num4);
void write_byte(uchar date);
uchar read_byte();
void get_tem();
void main()
{
init();
while(1)
{
// uchar num;
get_tem();
// for(num=20;num>0;num--)
// disp(a1,a2,a3,a4);
}
}
void reset()
{
uchar st=1;
DQ_HIGH();
NOP();NOP();
while(st)
{
DQ_LOW();
delayus(70,30);
DQ_HIGH();
delayus(4,4);
if(DQ==1)
st=1;
else
st=0;
delayus(50,10);
}
}
void write_byte(uchar date)
{
uchar i,temp;
DQ_HIGH();
NOP();NOP();
for(i=8;i>0;i--)
{
temp=date&0x01;//01010101
DQ_LOW();
delayus(0,0);
if(temp==1)
DQ_HIGH();
delayus(2,2);
DQ_HIGH();
date=date>>1;//00101010
}
}
uchar read_byte()
{
uchar i,date;
static bit j; //定义一位
for(i=8;i>0;i--)
{
date=date>>1;
DQ_HIGH();
NOP();NOP();
DQ_LOW();
NOP();NOP();NOP();NOP();NOP();NOP();
DQ_HIGH();
NOP();NOP();NOP();NOP();
j=DQ;
if(j==1)
date=date|0x80;//1000 0000
delayus(1,1);
}
return (date);
}
void get_tem()
{
uchar tem1,tem2,num;
float aaa;
reset(); //复位
write_byte(0xCC);//跳过ROM
write_byte(0x44);//温度转换
for(num=100;num>0;num--)
disp(a1,a2,a3,a4);
reset();
write_byte(0xCC);
write_byte(0xBE);
tem1=read_byte();
tem2=read_byte();
aaa=(tem2*256+tem1)*6.25; //此处的结果为浮点数
temper=(int)aaa; //强制转换成整型送入temper
a1=temper/1000;
a2=temper00/100;
a3=temper0/10;
a4=temper;
}
void delayus(uint x,uchar y)
{
uint i;
uchar j;
for(i=x;i>0;i--);
for(j=y;j>0;j--);
}
void delay(uint x)
{
uint a,b;
for(a=x;a>0;a--)
for(b=110;b>0;b--);
}
void init()
{
TRISD=0;
TRISA=0;
PORTD=0;
PORTA=0;
}
void disp(uchar num1,uchar num2,uchar num3,uchar num4)
{
PORTD=table[num1];//显示第一个数码管
PORTA=0x20;//0010 0000
delay(2);
PORTD=table1[num2];//显示第二个数码管
PORTA=0x10;//0001 0000
delay(2);
PORTD=table[num3];//显示第三个数码管
PORTA=0x08;//0000 1000
delay(2);
PORTD=table[num4];//显示第四个数码管
PORTA=0x04;//0000 0100
delay(2);
}
-----------------------------------------------------------------------------------------------------------------