PIC单片机编程的问题 刚学 不太懂
答案:4 悬赏:80 手机版
解决时间 2021-04-01 17:29
- 提问者网友:我没有何以琛的痴心不悔
- 2021-04-01 08:06
PIC单片机编程的问题 刚学 不太懂
最佳答案
- 五星知识达人网友:话散在刀尖上
- 2021-04-01 09:39
; 实例 供参考 可以直接仿真,多看看实例 会有帮助的。
; *********************************************************************
; * 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 ; 程序结束符
全部回答
- 1楼网友:骨子里都是戏
- 2021-04-01 11:33
先找个范例,按照范例来写!然后再一步步增加功能!
- 2楼网友:洎扰庸人
- 2021-04-01 10:35
以前没编过??先找人帮你入门吧。
- 3楼网友:鱼芗
- 2021-04-01 10:10
你好,首先我没用过MAPLAB IDE,我不知道它是否支持你这样写程序,如果用我现在用的仿真器,这段程序是无法编译的,先不谈语法,这段程序无头文件无程序入口。你去找下MAPLAB IDE的错误讯息,会告诉你ERROR152 129分别代表什么。上面显示的是,你这段程序除了伪代码段从第四行开始其他都错了,我只看出最后一行意思是你程序没有期望的END,但是我这里ICE有没有END都无所谓,所以你还是找下你那个IDE的错误讯息吧,所有的错误讯息都会告诉你是为什么,看ERROR后面的数字就行了。
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
推荐资讯