PIC单片机-测试例程汇总

内容包括PIC单片机C语言之PIC16F887(4MHz晶振)常用外设的测试例程。紫色文字是超链接,点击自动跳转至相关博文。持续更新,原创不易!

目录:

一、端口的定义与while(1)的使用

二、延时

1、通过语句延时程序(带参数)

2、通过语句延时程序(不带参数)

3、C程序延时时间计算

4、keil时间调试

三、外设

1、单按键检测与蜂鸣器发声(可控制发几声)

2、I2C端口模拟

3、DS18B20数字温度传感器(数码管显示)


一、端口的定义与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);
void disp(uchar num1,uchar num2,uchar num3,uchar num4);
void write_byte(uchar date);
uchar read_byte(void);
void get_tem(void);

void main(void)
{
   init();
   while(1)
   {
      // uchar num;
      get_tem();
      // for(num=20;num>0;num--)
      //  disp(a1,a2,a3,a4);
   } 
}
void reset(void)
{
   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(void)
{
   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(void)
{
   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(void)
{
   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);
}

人有两条路要走,一条是必须走的,一条是想走的,你必须把必须走的路走漂亮,才可以走想走的路。觉得不错,动动发财的小手点个赞哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱上电路设计

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值