PIC单片机编程的问题 刚学 不太懂

PIC单片机编程的问题 刚学 不太懂,第1张

 实例 供参考 可以直接仿真,多看看实例  会有帮助的。

 *********************************************************************

 *      GPIO0-V  GPIO1-I  GPIO2-LED1  GPIO4-LED2  GPIO5-OUT          *

 *      GPIO3-10K                                                    *

 *********************************************************************

          LIST P=12F675

          INCLUDE "P12F675.INC"   包含MPLAB预定义的头文件

          __CONFIG(0x3FC4)        11 ---1 1100 1000  设定配置字信息

                                  _CPD_OFF & _CP_OFF & _BODEN_ON & _MCLRE_OFF 

                                  关代码-数据保护,    掉电复位使能,内部复位,

                                  _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT

   歼答                               上电复位延时使能,关看门狗,内部振荡无时钟输出

 *************************************************

 * 寄存器定义及RAM分配                           *

 *************************************************

        ERRORLEVEL -302            编译输出结果中不要显示message

        cblock 0x20                通用变量定义从该地址开始

          W_TEMP                     中断服务程序用来临时保存W和STATUS 

          STATUS_TEMP

          FLAGS                      程序要使用的状态标志寄存器

          PWM_HIGH:2                 新的PWM高电平时间,保留两个字节

          PWM_LOW:2                  新的PWM低电平时间,保留两个字节

          PWM_HIGH_CURRENT:2         当前PWM的高电平时间锁存

          PWM_LOW_CURRENT:2          当前的PWM低电平时桐耐间锁存

          COUNTER                    AD采样次数计数

          adsum:2                    16位的AD累加结果,用于平均运算,两个字节

          temp:2                     用于数学运算的临时变量,两个字节

          endc                       结束cblock变量定义

        count   EQU   38H

          result  EQU   39H

************************************************

I/O引脚初始化                                  *

以及 A/D 初始化                                *

************************************************

GP0 = 模拟电压输局改春入

GP1 = 没有使用

GP2 = 没有使用

GP3 = 只能作为输入,连接10K下拉电阻到地,ICSP烧录会使用该引脚

GP4 = PWM1  输出引脚

GP5 = PWM2  输出引脚

         / *** *** *** *** *** /   代换定义

#define PWM_OUTPUT     GPIO,2   GPIO,4

#define LOAD_PWM       FLAGS,0

#define CALCULATE_AD   FLAGS,1

#define PWM_TICKS      .1024    PWM时间片的个数,如果PWM的分辨率是10位,

#define TEST_PWM_HIGH  .512     用于测试的50%占空比,高电平时间等于PWM时间片的一半

#define TEST_PWM_LOW   PWM_TICKS-TEST_PWM_HIGH   低电平时间等于PWM时间片减高电平时间

#define ISR_DELAY      .16      从Timer1溢出到进入中断重新装载Timer1值的延时,

                                可通过软件模拟来确定该值

#define NUM_AD_SAMPLES .16      AD采样次数

#define AD_TIME_INTERVAL .10    0xFF - (.245)   AD时间间隔,10个cycle的循环

         / *** *** *** *** *** /   定义双字节常数减变量的宏

           const_input - input = output

sub_const_16 macro const_input, input, output

          movlw   low const_input    W = low 双字节常数   L

          movwf   temp

          movlw   high const_input   W = high 双字节常数 H

          movwf   temp+1

          movf    input,w            W = input

          subwf   temp,w             W = temp - W 

          movwf   output             output = W

          movf    input+1,w          W = input+1

          btfss   STATUS,C           C = 1 ->

          incf    input+1,w          W = input+1 + 1

          subwf   temp+1,w           W = temp+1 - W 

          movwf   output+1           output+1 = W

          endm

         / *** *** *** *** *** /   定义双字节常数加变量的宏

           const_input + input = output

add_const_16 macro const_input, input, output

          movlw   low const_input    W = low 双字节常数   L

          movwf   temp

          movlw   high const_input   W = high 双字节常数 H

          movwf   temp+1

          movf    input,w            W = input

          addwf   temp,w             W = temp + W 

          movwf   output             output = W

          movf    input+1,w          W = input+1

          btfsc   STATUS,C           C = 0 ->

          incf    input+1,w          W = input+1 + 1

          addwf   temp+1,w           W = temp+1 + W 

          movwf   output+1           output+1 = W

          endm

         / *** *** *** *** *** /   程序开始

           / *** *** *** *** *** /

        org     0000H              芯片复位入口地址0x00

          goto    MAIN000            主程序

         / *** *** *** *** *** /   中断服务子程序

           / *** *** *** *** *** /

           INTCON,T0IF---TMR0  溢出    INTCON,INTF---GP2/INT外部中断

           INTCON,GPIF---GP5-GP0 引脚电平发生了变化

           PIR1,EEIF---EEPROM 写 *** 作完成  PIR1,ADIF---A/D 转换完成

           PIR1,CMIF---比较器输入已改变   PIR1,TMR1IF---TMR1  溢出

        org     0004h              中断入口地址0x0004

INTCON00  movwf   W_TEMP             W_TEMP = W  保存

          swapf   STATUS,W           STATUS_TEMP = STATUS

          movwf   STATUS_TEMP

          bcf     STATUS,RP0         选择Bank 0

INTCON02  movlw   b'00000100'        把W的第四位置高,其他都是零

          xorwf   GPIO,F             和GPIO异或,也就是把PWM输出脚的电平反转

                                     判断中断种类

INTCON03  bcf     PIR1,TMR1IF        清 T1 中断标志 Timer1 中断

          movlw   HIGH 3CAFH         Timer1 = 50 mS  C350H

          movwf   TMR1H              FFFFH - C350H = 3CAFH

          movlw   LOW 3CAFH

          movwf   TMR1L

        bsf     CALCULATE_AD       置位 A/D 转换标志

          bsf     LOAD_PWM           置位 PWM 标志

INTCON08  swapf   STATUS_TEMP,W      恢复STATUS寄存器

          movwf   STATUS

          swapf   W_TEMP,F           恢复W寄存器

          swapf   W_TEMP,W

          retfie                     从中断返回

         / *** *** *** *** *** /   主程序

           / *** *** *** *** *** /

MAIN000   clrf    GPIO               初始化GPIO端口寄存器为零

          bsf     STATUS, RP0        选择Bank 1

          call    0x3FF              读内部振荡出厂校准字,返回值在W寄存器内

          movwf   OSCCAL             内部振荡器校准

        movlw   b'11000011'        设置GP<0>为输入,所有其他口为输出

          movwf   TRISIO         

        movlw   01h                使能Timer1中断 01h

          movwf   PIE1

        movlw   b'00010001'        AD采用FOSC/8 时钟,GP2是模拟口,

          movwf   ANSEL              其他口为数字IO

        movlw   b'00001000'        Timer0设置为使用内部指令周期,无预分频

          movwf   OPTION_REG

        bcf     STATUS, RP0        选择Bank0

          movlw   b'10000001'        A/D是右对齐格式,Vdd为参考,GP0作为AD输入口

          movwf   ADCON0

        movlw   b'00000111'        关掉内部比较器,让比较器的输入都为数字口

          movwf   CMCON

        movlw   0C0h               使能周边外设中断和全局中断

          movwf   INTCON

        movlw   b'00000001'        Timer1是1:1预分频,内部时钟源,

          movwf   T1CON              振荡频率/4,不带门控

        movlw   .16                AD 次数 = 10

          movwf   COUNTER

MAIN010   btfss   CALCULATE_AD       = 1 ->  主循环

          goto    MAIN010

          bcf     CALCULATE_AD       清 A/D 转换标志

        bsf     STATUS,RP0         选择bank1

          movf    ADRESL,W           W = AD L

          addwf   adsum,F            adsum = AD L

          btfsc   STATUS,C           C = 0 ->

          incf    adsum+1,F          adsum+1 = adsum+1 + 1

          bcf     STATUS,RP0         选择Bank0

          movf    ADRESH,W           W = AD H

          addwf   adsum+1,F          adsum+1 = AD H

          bsf     ADCON0,GO_DONE     启动 AD 下一次转换

          decfsz  COUNTER,F          转换 计数器 - 1 = 0 ->

          goto    MAIN010            循环

        movfw   adsum

          movwf   result             result = w

          CALL    LED000

          movfw   adsum+1

          movwf   result             result = w

          CALL    LED000

        movlw   .16                AD 次数 = 10

          movwf   COUNTER

          clrf    adsum              清 A/D 累加和 / 平均值 寄存器

          clrf    adsum+1

        goto    MAIN010

         / *** *** *** *** *** /   串行输出

LED000    movlw   8                  串行输出 8 位 w = 8

   movwf   count              count = w

LED001    bcf     TRISIO,4           清零   

    btfsc   result,0           result.7=0 ->

   bsf     TRISIO,4           0010 0000

   bsf     TRISIO,5      产生时钟脉冲 GP4 = 1

   bcf     TRISIO,5                        GP4 = 0

   RRF     result,1           左移获取下一个结果位

   decfsz  count,1      - 1

   goto    LED001             <> 0    循环下位

   RETURN               = 0

         / *** *** *** *** *** / 

        end                        程序结束符

共阳共阴只是你在选COM端时给其高低电平的问题无关大雅

我给一段PIC单片机的程序让你参考一下,如果你看懂的话应该能做出来了

#include <pic.h>

#include <math.h>

//此程序实现计时秒表功能,时钟显示范围00.00~99.99秒,分辨度:0.01秒

unsigned char s0,s1,s2,s3;

//定义0.01 秒、0.1 秒、1秒、冲空物10秒计时器

unsigned char s[4];

unsigned char k ,data ,sreg;

unsigned int i;

const table[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90};

//不带小数点的显示段码表

const table0[10]={0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10};

//带小数点的显示段码表

//TMR0初始化子程序

void tmint()

{

T0CS=0;//TMR0工散液作于定时器方式

PSA=1; //TMR0不用分频

T0IF=0; //清除TMR0的中断标志

T0IE=1; //TMR0中断允许

}

//spi显示初始化子程序

void SPIINIT()

{

PIR1=0;

SSPCON=0x30;

SSPSTAT=0xC0;

//设置SPI的控制方式,允许SSP方式,并且时钟下降沿发送。与"74HC595,当其

//SCLK从低到高跳变时,串行输入寄存器"的特点相对应

TRISC=0xD7; //SDO引脚为输出,SCK引脚为输出

TRISA5=0;//RA5引脚置为输出,输出显示锁存信号

}

//系统其它部分初始化子程序

void initial()

{

TRISB1=0;

TRISB2=0;

TRISB4=1;

TRISB5=1;//设置与键盘有关的各口的输入输出方式

RB1=0;

RB2=0; //建立键盘扫描的初始条件

}

//SPI传输亏升数据子程序

void SPILED(data)

{

SSPBUF=data; //启动发送

do {

}while(SSPIF==0);

SSPIF=0;

}

//显示子程序,显示4位数

void dispaly()

{

RA5=0; //准备锁存

for(k=4;k>0;k--)

{

data=s[k-1];

if(k==3) data=table0[data];//第二位需要显示小数点

else data=table[data];

SPILED(data); //发送显示段码

}

for(k=0;k<4;k++)

{

data=0xFF;

SPILED(data); //连续发送4个DARK,使显示好看一些

}

RA5=1; //最后给锁存信号,代表显示任务完成

}

//软件延时子程序

void DELAY()

{

for(i = 3553; --i ;) continue;

}

//键扫描子程序

void KEYSCAN()

{

while(1){

while(1)

{

dispaly(); //调用一次显示子程序

if ((RB5==0)||(RB4==0)) break;

}

DELAY(); //若有键按下,则软件延时

if ((RB5==0)||(RB4==0)) break;//若还有键按下,则终止循环扫描,返回

}

}

//等键松开子程序

void keyrelax()

{

while(1){

dispaly();//调用一次显示子程序

if ((RB5==1)&&(RB4==1)) break;

} //为防止按键过于灵敏,每次等键松开才返回

}

//系统赋值初始化子程序

void inizhi()

{

s0=0x00;

s[0]=s0;

s1=0x00;

s[1]=s1;

s2=0x00;

s[2]=s2;

s3=0x00;

s[3]=s3; //s0=s1=s2=s3=0,并放入显示缓冲数组中

sreg=0x00;//tmr0中断次数寄存器清0

}

//中断服务程序

void interrupt clkint(void)

{

TMR0=0X13; //对TMR0写入一个调整值。因为写入TMR0后接着的

//两个周期不能增量,中断需要3个周期的响应时间,

//以及C语言自动进行现场保护要消耗周期

T0IF=0; //清除中断标志

CLRWDT();

sreg=sreg+1;//中断计数器加1

if(sreg==40)//中断次数为40后,才对S0,S1,S2,S3 *** 作

{

sreg=0;

s0=s0+1;

if(s0==10){

s0=0 ;

s1=s1+1;

if(s1==10){

s1=0 ;

s2=s2+1;

if(s2==10){

s2=0;

s3=s3+1;

if(s3==10) s3=0 ;

}

}

}

}

s[0]=s0;

s[1]=s1;

s[2]=s2;

s[3]=s3;

}

//主程序

main()

{

OPTION=0XFF;

tmint(); //TMR0初始化

SPIINIT();//spi显示初始化

initial(); //系统其它部分初始化

di(); //总中断禁止

while(1) {

inizhi();//系统赋值初始化

KEYSCAN(); //键扫描,直到开始键按下

keyrelax(); //等键松开

ei();//总中断允许

TMR0=0X08;

KEYSCAN(); //键扫描直到停止键按下,在键扫描时有显示

keyrelax() ; //等键松开

di();//总中断禁止

KEYSCAN(); //键扫描到清0键按下,在键扫描时有显示

keyrelax() ; //等键松开

}

}

#include <pic.h>

#define uchar unsigned char

unsigned char RC_data

int hz=0

void usart_init()

{

TRISC6=0//RC6:TX为发送口

TRISC7=1/扮中/RC7:RX为接收口

TXSTA=0x24//使能发送,高波特率

RCSTA=0x90//串口使能,连续接收

SPBRG=0x19//设置波特率9600

TRISD=0x00//D口为输出

PORTD=0xF0//D口清零

// 中断设置

PIR1=0X00

PIE1=0X00

RCIE=1

TXIE=0

INTCON=0X00

PEIE=1

GIE=1

}

void interrupt uart()

{

if(1==RCIF)

{

RCIF=0

RC_data=RCREG

TXREG=RC_data

}

if(1==TXIF)

{

TXIF=0

PORTD=0X0F

}

}

main()

{

usart_init() //初始化

while(1)

}

单片机编程,本身不区分RS232与RS485。如果厅旅山你需镇大要RS485通讯,可以用MAX488芯片实现485通讯。再用个RS232-485转换器,接到计算机上,用个串口调试工具就能用了。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12493084.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存