PIC单片机

       PIC芯片所用编译器是MPLAB X IDE,刚开始接触PIC单片机,也是一脸茫然,然后查阅资料逐渐了解、运用编译器,这里我就不说编译器怎么使用了,下面我将以PIC12LF1822芯片为例,简单来说说我见解,分别说说时钟、串口、定时器、ADC、触摸按键。

一、时钟

     时钟一般有内部时钟(系统时钟)、外部时钟。单片机时钟可选择系统时钟、外部时钟。时钟相当于单片机的心脏,每跳动一下,整个单片机的各个电路就同步的动作一下。

  时钟配置

   配置PIC12LF1822时钟,一般只配置OSCCON寄存器就可以实现一些简单的功能,OSCCON寄存器如下图

     时钟初始化:                     

void Init_Fosc()
{
    OSCCON = 0xf0;//时钟频率32MH,内部时钟;
}

二、串口通信(EUSART)

      当今单片机一般都是用的异步串行通信,至于什么是异步串口通信这里就不累赘了。(关于串口可以看我另一个文章)

  配置串口

       一般配置串口会去配置单片机的哪个管脚为数据发送脚、数据接收脚、设置波特率、发送中断使能位、接受中断使能位、发送中断标志位、接收中断标志位。

      PIC12LF1822的波特率计算公式:

             波特率 = 系统时钟/(4[n+1]) 将计算出来的n值放入,波特率的高8位和低8位;

             比如我们把波特率定位9600,时钟定为4MHz。计算出 n = 25,则波特率寄存器装值如下:

                            SPBRGH=0;
                            SPBRGL=0x19;//Baud Rate is 9600

串口通信代码如下:

#include <xc.h> 
char ch;
void Init_Uart(void)
{
    RXDTSEL = 0;    //RA1->Rx
    TXCKSEL = 0;    //RA0->Tx
    TXSTA = 0x2c;   // Slave mode and Transmit enabled
    RCSTA = 0x90;   // Enables receiver
    BAUDCON = 0x80; //Uart enabled 
    SPBRGH = 0;
    SPBRGL = 0x19;  //Baud Rate is 9600
    RCIE = 1;       //open Uart recive interput
    TXIE = 0;       //close Uart trismit interput
}

void main(void)
{
    Init_Uart();
    while(1);
    return;
}

void interrupt ISR(void)       //????????? 
{ 
    if(RCIE==1)  //串口接受中断
    {
        ch = RCREG;
        RCIE = 0;
        TXIE = 1;       //open Uart trismit interput
        TXREG = d         
        while(TXIF == 0);   //wait Trismit
        TXIF = 0;
    }
   
}

三、定时器 

      定时器是用来计时、计数的,几乎任何单片机程序都会用到定时器。配置定时器一般会配置时钟选择、中断使能、中断标志位、装初值、预分频等。定时器一般溢出中断后需要重新赋初值。

定时器与预分频器

        我在最开始学单片机始终没搞明白预分频,其实预分频也挺好理解的。在没有预分频器情况下。开启定时器每隔一个指令周期定时器就加一。假设时钟是4MHz  ,定时器时钟 = 系统时钟/4,也就是每隔 1us 定时器加一。如果有了预分频器假设预分频器设置成2分频,定时器就 每隔2us定时器加一。如果预分频器设置成4分频,定时器就 每隔4us定时器加一,以此类推。下图以预分频和周期来分析定时器:

定时器0(Time0)的简单代码如下:

void Init_Timer0(void)
{    
    OPTION_REG=0x87;   //设置预分频位256
    TMR0IE=1;          //Timer0溢出中断使能 
    TMR0IF=0;          //清空Timer0中断标志位
    TMR0=61;           //给Timer0赋初值,使Timer0溢出时间为50ms
}
void interrupt ISR(void)       //?中断函数
{ 
    if(TMR0IF==1)
    {
        /*该处写中断后你想实现的代码,并清零中断标志位、给Timer0重新装初值*/
        TMR0IF=0;
        TMR0=61;    //重新装初值    
    }
}

四、ADC 

      ADC即模/数转换器,把模拟信号转化为数字信号。数字量就是用 0和1 组成二进制代码表示某个信号大小的量。AD转换一般通过采样、量化、编码三个步骤。

 配置ADC

      ADC控制寄存器图如下:

 

ADC简单代码如下:

void AD_Init()
{ 
     ANSELA = 0x01;   //RA0为模拟口
     TRISA = 0x01;    //RA0为输入
     ADCON0 = 0x01;  //选择通道AN0即RA0管脚,使能ADC
     ADCON1 = 0x20;  //左对齐,时钟为F OSC /32
}
unsigned int AD_get_value()
{
    unsigned int value = 0;
    ADCON0bits.ADGO=1;          //开始转换
    while(ADCON0bits.GO==1);    //等待转换结束

    value=(unsigned int)ADRESH;  //强制类型转换,因为ADRESH是字符型的只能表示8位二进制。
                                 //所以必须转换成可以容纳10位二进制的整型
    value= value<<2;             // 将高两位左移8位
    value += ADRESL;             //低八位加入ADRESL的值

    return value;
}
unsigned int AD_average_value()
{
    unsigned int AD_value[10] = {0};
    unsigned int AD_average_value = 0;
    unsigned int i;

    for(i=0;i<10;i++)
    {
        AD_value[i] = AD_get_value();
        AD_average_value += AD_value[i];
    }

    AD_average_value = AD_average_value/10;
    
    return AD_average_value;
}

 

五、触摸按键

按键触摸原理

   记录电容充放电的次数,当手触摸时电容充放电次数低于平均值,具体原理看《AN1101》、《AN1103电容触摸传感的软件处理》。

配置触摸按键步骤

  1. 设置芯片哪个管脚为触摸脚

     

  2. 将Timer1时钟源设置为电容式传感振荡器。

Timer1来计电容充放电的次数,由Timer0来计时。Timer0每隔段时间触发一次中断,来读取Timer1充放电的次数。必须设置Timer0的预分频器,使得Timer0比Timer1先溢出。value = TMR1L + (unsigned int)(TMR1H << 8)。

 

      3.判断当前频率次数是否低于正常的未触压的平均值。

触摸按键代码如下

#include <xc.h>  
#define true 1
#define false 0
unsigned char flag;
static int index;
static int num;
long raw[2] = {0};
long average[2] = {0};
long trip[2] = {2256,7000};
unsigned int CPS[2] = {0x02,0x03};
void init(void)
{
    /*init_fosc*/
    OSCCON = 0x6a;//4MHz
    
    /*init_interrupt*/
    INTCON = 0xc0;//open interrupts
    /*init_gpio*/
    ANSELA = 0x14;//RA0,RA5 is Digital,RA2,RA4 is  Analog input
    TRISA = 0x16; //RA1,RA2,RA4 is input,RA0,RA5 is output
    
    /*init_uart*/
    /*
    RXDTSEL=0;//RA1->Rx
    TXCKSEL=0;//RA0->Tx
    TXSTA=0x2c;//?????????
    RCSTA=0x90;//?????????
    BAUDCON=0x80;//baud raie control register
    SPBRGH=0;
    SPBRGL=0x19;//Baud Rate is 9600
    RCIE=1; //open Uart recive interput
    TXIE=0; //close Uart trismit interput
   */
    /*init_Timer0; interrupt function need clear interrupt Flag bit*/
    OPTION_REG=0x87; //Prescaler is 256
    TMR0IE=1;//Timer0 Overflow Interrupt Enable 
    TMR0IF=0;//clear Timer0 Overflow Interrupt Flag bit
    TMR0=61;//give Timer0 initial value,so 50ms
    
    /*init_timer1*/
    T1CON=0xc5; //enable Timer1 , Clock Prescale is 1:1
    TMR1IF=0;//clear Timer1 Overflow Interrupt Flag bit
    TMR1IE=1;//Enables the Timer1 overflow interrupt
    TMR1H=0;//give Timer1 initial value,so 500ms
    TMR1L=0;
    
    /*touch_init*/
    CPSCON0=0x8c;
    CPSCON1=0x02;
}

void putch(unsigned char byte) //重定义
{
    TXREG = byte;         //Uart_Data 
    while(TXIF == 0);   //等待发送
    TXIF = 0;
}

void main(void)
{
    init();
    flag = false;
    index = 0;
    num = 0;
    //PORTA = 0x21;
    unsigned int i;
    while(1)
    {   
        if(flag)
        {
            TMR0IE=0;   //close Timer0 Overflow Interrupt
            flag = false;
               
            if(raw[index] < average[index] - trip[index])
            {
                switch(index)
                {
                    case 0:
                       //printf("The bot button is pressed\r\n");
                        PORTA |= 0x20;
                        break;
                    case 1:
                       //printf("The top button is pressed\r\n");
                        PORTA |= 0x01;
                        break;
                    default:
                        break;            
                }
            }
            else
            {
                if((raw[0] > average[0] - trip[0]) && (raw[1] > average[1] - trip[1]))
                {
                    PORTA = 0x00;
                }
                
                average[index] = average[index] + (raw[index] - average[index])/16;
            }
            
            index++;
            if(index >= 2)
                index = 0;
            
            TMR0IE=1;  //close Timer0 Overflow Interrupt
            TMR0IF=0;  //clear Timer0 Overflow Interrupt Flag bit
            TMR0=61;   //give Timer0 initial value,so 50ms
            TMR1IF=0;
            TMR1H=0;   //give Timer1 initial value
            TMR1L=0;
        }            
        
    }
    return;
}

void interrupt ISR(void)     
{ 
    if(TMR0IF==1)
    {
        flag = true;
        raw[num] = TMR1L + (unsigned int)(TMR1H << 8);
        num++;
        if(num>=2)
        {
            num = 0;
        }
        CPSCON1 = CPS[num];
        TMR0IF=0;//clear Timer0 Overflow Interrupt Flag bit
        TMR0=61;//give Timer0 initial value,so 50ms
        TMR1IF=0;
        TMR1H=0;//give Timer1 initial value
        TMR1L=0;
             
    }
    if(TMR1IF==1)
    {
        TMR1IF=0;//clear Timer1 Overflow Interrupt Flag bit
        TMR1H=0;//give Timer1 initial value,so 100ms
        TMR1L=0;
    } 
}

 

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值