
1 static volatile unsigned TMR1 @ 0x0E;
0x0E 是寄存器地址。 表示这个TMR1是寄存器0x0E的值。 具体这个寄存器是做什么用的,需要看你芯片的datasheet,比如 16F874A 16F877A 这个都是计数寄存器的地址。
2 PopQueue应该是一个d出队列的函数。
将队列首d出到msg中,返回值为PopSuccess表示取数据成功,取到的数据会存在msg中。
一般用于中断传数据给主线程。这个在主线程中接收。
3 __CONFIG(x) 一般是配置寄存器的。
想知道哪种,给你粘贴,下面是一些计算子程序
;
;一、十六位二进制转换为BCD数子程序
;
MOVLW 10H ;
MOVWF CNT ;
BCF STATUS,C ;
CLRF R2 ;
CLRF R1 ;
CLRF R0 ;
LOOP RLF AL ;
RLF AH ;
RLF R0 ;
RLF R1 ;
RLF R2 ;
DECFSZ CNT ;
GOTO ADJDEC ;
RETURN
ADJDEC MOVLW R0 ;
MOVWF FSR ;
CALL ADJBCD ;
MOVLW R1 ;
MOVWF FSR ;
CALL ADJBCD ;
MOVLW R2 ;
MOVWF FSR ;
CALL ADJBCD ;
GOTO LOOP ;
ADJBCD MOVLW 3H ;
ADDWF INDF,W ;
MOVWF TMP ;
BTFSC TMP,3 ;
MOVWF INDF ;
MOVLW 30H ;
ADDWF INDF,W ;
MOVWF TMP ;
BTFSC TMP,7 ;
MOVWF INDF ;
RETURN
;
;乘法宏
;两个八位无符号数乘法,乘积为十六位。部分积右移相加算法:乘数带进位右移一位,
;检查进位是否为一,若是一,部分积寄存器加被乘数,否则不加;然后部分积寄存器
;带进位右移一位;重复上述过程直至循环次数为八结束。
;
;宏的引用格式:MUL A,B
;完成 *** 作: (A)(B)---(A,B)
;影响状态位:C、Z和DC
;88位乘法宏MUL,结果的高字节部分存入(A),低字节存入(B)
;
MUL MACRO A,B ;
LOCAL MLOOP ;
;
;如只用乘法子程序,就下段。
;
CLRF TMPA ;
CLRF TMPB ;
MOVLW 8 ;
MOVWF CNT ;
MOVF A,W ;
BCF STATUS,C ;
MLOOP RRF B ;
BTFSC STATUS,C ;
ADDWF TMPA ;
RRF TMPA ;
RRF TMPB ;
DECFSZ CNT ;
GOTO MLOOP ;
MOVF TMPA,W ;
MOVWF A ;
MOVF TMPB,W ;
MOVWF B ;
;
ENDM
;
;除法宏DIV
;除法是乘法的逆运算。与十进制长除法类似,从被除数的最高有效位开始,把被除数左移
;一位至余数上,如果余数不够减去除数,则商寄存器左移,移入位为零,反之移入位为一
;余数减去被除数,把被除数的下一位移至除数上。重复上述过程直至处理完所有位。
;
;宏的引用格式:DIV A,B
;完成 *** 作: (A)为商部分,(B)为余数部分
;影响状态位:C、Z和DC
;8/8位除法宏DIV,结果(A)为商部分,(B)为余数部分
;
DIV MACRO A,B ;
LOCAL MLOOP ;
;
;如只用除法子程序,就下段。
;
MOVF A,W ;
MOVWF TMPA ;
MOVF B,W ;
MOVWF TMPB ;
MOVLW 8 ;
MVOWF CNT ;
CLRF A ;
CLRF B ;
DLOOP BCF STATUS,C ;
RLF TMPA ;
RLF B ;
MOVF TMPB,W ;
SUBWF B,W ;
BTFSC STATUS,C ;
MOVWF B ;
RLF A ;
DECFSZ CNT ;
GOTO DLOOP ;
;
ENDM ;
;
;间接寻址
CLRF R0 ;清除R0寄存器里的内容
MOVLW R0 ;
MOVWF FSR ;将R0寄存器的地址送入间接寻址指针FSR
MOVF INDF,0 ;
MOWF TEMP ;将间接寻址指针FSR所指地址R0寄存器里的内容送入TEMP
MOVLW 88H ;
MOVWF INDF ;将88H送入间接寻址指针FSR所指地址R0寄存器里
;
;将两位BCD数送入显示
;显示十位BCD数
DISPLAY SWAPF TEMP,W ;将TEMP寄存器里的内容的高低字节交换并送入W
ANDLW 0FH ;将0FH与W寄存器里的内容相与并送入W
CALL CODE_TAB ;查表取段码
MOVWF PORTD ;送入PORTD端口
MOVLW 1H ;
MOVWF PORTC ;选通PORTC,1
CALL DELAY ;调用延时
;显示个位BCD数
MOVF TEMP,W ;
ANDLW 0FH ;
CALL CODE_TAB ;
MOVWF PORTD ;
MOVLW 2H ;
MOVWF PORTC ;
CALL DELAY ;
;
;16位二进制除以8位二进制
;
DIV16
MOVF A,0
MOVWF DIV_H
MOVF BX,0
MOVWF DIV_L ;被除数高低字节分别送进各寄存器
MOVLW 9H
MOVWF DIVB ;将除数送进寄存器
MOVLW 10H
MOVWF CNT ;按被除数位数设定移位次数
CLRF AL
CLRF AH
CLRF BX
DLOOP
BCF STATUS,C
RLF DIV_L
RLF DIV_H
RLF BX
MOVF DIVB,W
SUBWF BX,W
BTFSC STATUS,C
MOVWF BX
RLF AL
RLF AH
DECFSZ CNT
GOTO DLOOP
RETURN
;
;8位乘以16位二进制乘法运算程序
;
MUL8
CLRF TMPA ;清除积的高位寄存器
CLRF TMPB ;清除积的中位寄存器
CLRF TMPC ;清除积的低位寄存器
MOVLW 10H ;因为8位二进制乘以16位二进制,乘数为16位,移位乘数,所以移位次数为16次
MOVWF CNT ;
MOVF BX,W ;将8位被乘数送进W
BCF STATUS,C;
MLOOP RRF TEMP_H ;
RRF TEMP_L ;带C循环右移16位乘数
BTFSC STATUS,C ;
ADDWF TMPA ;
RRF TMPA ;
RRF TMPB
RRF TMPC
DECFSZ CNT ;
GOTO MLOOP ;
MOVF TMPA,W ;
MOVWF AA ;
MOVF TMPB,W ;
MOVWF A
MOVF TMPC,W ;将乘积送进各寄存器。
MOVWF BX
RETURN
INDF 和 FSR两个寄存器构成了一个间接寻址的作用。
FSR有点像C语言中的指针,INDF是一个虚拟的寄存器,对它 *** 作其实是对FSR锁指向的内存单元 *** 作。
简单的说,当20h这个数赋给了FSR,那么就是FSR作为指针指向了内存中地址为20h的这个单元(以下就用<20h>来表示这个单元,以区别十六进制的20h这个数值),此时INDF就被映射到<20h>。
从头说起:
1:W被赋值20h这个数;2:FSR被赋值和W寄存器相同的数20H,此时FSR指向了<20h>;3:此时W寄存器因为没被改变过,所以其数值依然是十六进制的20h那么MOVWF 20H其实就是把W里的数据赋值给<20h>这个内存单元 也就是 <20h> = 20H ;
4:重点来了 INCF INDF,让INDF自加1。前面说了对INDF *** 作其实就是对FSR所指向的单元 *** 作,也就等同于 INCF <20h>(真正程序里不能这么写的,因为<20h>这杨写法是错误的) 类似C与语言中的<20h>++
5:FSR自加1,FSR内部的值等于21h所以FSR指向了<21h>这个内存单元。
6:<20h>单元的数值高4位和低4位转换一下数据。所以 <20h> = 02h
7:把<20h>的内容赋值给W寄存器,所以w = 02h
8:FSR此时 等于21h ,把21h和W的02h做与运算,结构 0 赋值给FSR。
//09/10/24
//lcd1602显示时间 日期 星期 温度
//通过按键校时:K10--小时,K11--分钟,K12--秒(归零),K13-星期,BR1--年,RB2--月,RB3--日。
//芯片要求:PIC16F877A
#include<pich> //包含单片机内部资源预定义
__CONFIG(0x1832);
//芯片配置字,看门狗关,上电延时开,掉电检测关,低压编程关,加密,4M晶体HS振荡
#define i_o RB4 //定义DS1302的数据口
#define sclk RB0 //定义DS1302的时钟口
#define rst RB5 //定义DS1302的复位口
#define rs RA1 //1602
#define rw RA2
#define e RA3
# define DQ RA0 //定义18B20数据端口
unsigned char TLV=0 ; //采集到的温度高8位
unsigned char THV=0; //采集到的温度低8位
unsigned char bai;
unsigned char shi; //整数十位
unsigned char ge; //整数个位
unsigned char shifen; //十分位
float temp;
void display();
//定义读取时间和日期存放表格
char table1[7];
//定义0-9的显示代码
const char table2[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char rx_data,read_data,count,sec,min,hour,day,mon,week,year,time;
//----------------------------------------------
//ds18b20部分
//------------------------------------------------
//延时函数
void delay1(unsigned int x)
{
unsigned int i;
for(i=x;i>0;i--);
}
//------------------------------------------------
//延时函数
void delay2(char x,char y)
{
char z;
do{
z=y;
do{;}while(--z);
}while(--x);
}
//其指令时间为:7+(3(Y-1)+7)(X-1)如果再加上函数调用的call 指令、页面设定、传递参数花掉的7 个指令。
//则是:14+(3(Y-1)+7)(X-1)。
//
//初始化ds18b20
void ds18b20_init()
{
char presence=1;
while(presence)
{
TRISA0=0; //主机拉至低电平
DQ=0;
delay2(2,99); //延时503us
TRISA0=1; //释放总线等电阻拉高总线,并保持15~60us
delay2(2,8); //延时70us
if(DQ==1) presence=1; //没有接收到应答信号,继续复位
else presence=0; //接收到应答信号
delay2(2,60); //延时430us
}
}
//
//写ds18b20
void ds18b20_write_byte(unsigned char code)
{
unsigned char i,k;
for(i=8;i>0;i--)
{
k=code&0x01;
TRISA0=0;
DQ=0; //数据线拉低产生时间片
asm("nop");
asm("nop");
if(k) DQ=1; //写1则拉高数据电平
delay1(3); //延时42us,ds18b20对数据线采样
asm("nop");
TRISA0=1; //采样结束,释放总线,拉高电平
code=code>>1;
delay1(7); //延时82us
}
}
//
//读ds18b20
unsigned char ds18b20_read_byte()
{
unsigned char i,k;
for(i=8;i>0;i--)
{
k=k>>1;
TRISA0=0;
DQ=0; //数据线拉低再拉高产生读时间片
asm("nop");
asm("nop");
TRISA0=1;
asm("nop");
asm("nop");
if(DQ) k=k|0x80; //15us内要完成读位
delay1(6); //延时72us后释放总线
}
return (k);
}
//
//启动温度转换函数
void get_temp()
{
int i;
signed int t;
TRISA0=1;
ds18b20_init(); //复位等待从机应答
ds18b20_write_byte(0XCC); //忽略ROM匹配
ds18b20_write_byte(0X44); //发送温度转化命令
for(i=2;i>0;i--)
{
display(); //调用多次显示函数,确保温度转换完成所需要的时间
}
ds18b20_init(); //再次复位,等待从机应答
ds18b20_write_byte(0XCC); //忽略ROM匹配
ds18b20_write_byte(0XBE); //发送读温度命令
TLV=ds18b20_read_byte(); //读出温度低8
THV=ds18b20_read_byte(); //读出温度高8位
TRISA0=1; //释放总线
t=THV<<8;
t=t|TLV;
if(t<0) //负温度
{
temp=(~t+1)0062510+05; //负温度时,取反加1再乘以00625得实际温度,乘10+05显示小数点一位,且四舍五入
}
else
temp=t0062510+05; //正温度
if(t<0)
bai='-'; //负温度时百位显示负号
else
bai=(const) temp/1000+0x30; //百位
shi=((const) temp%1000)/100; //十位
ge=((const) temp%1000)%100/10; //个位
shifen=((const) temp%1000)%100%10; //十分位
NOP();
}
//---------------------------------------------
//------------DS1303部分-----------------------
//---------------------------------------------
//延时程序
void delay() //延时程序
{
int i; //定义整形变量
for(i=0x64;i--;); //延时
}
//写一个字节数据函数
void write_byte(unsigned char data)
{
int j; //设置循环变量
for(j=0;j<8;j++) //连续写8bit
{
i_o=0; //先设置数据为0
sclk=0; //时钟信号拉低
if(data&0x01) //判断待发送的数据位是0或1
{
i_o=1; //待发送数据位是1
}
data=data>>1; //待发送的数据右移1位
sclk=1; //拉高时钟信号
}
sclk=0; //写完一个字节,拉低时钟信号
}
//---------------------------------------------
//读一个字节函数
unsigned char read_byte()
{
int j; //设置循环变量
TRISB4=1; //设置数据口方向为输入
for(j=8;j--;) //连续读取8bit
{
sclk=0; //拉低时钟信号
rx_data=rx_data>>1; //接收寄存器右移1位
if(i_o==1) rx_data=rx_data|0x80;
sclk=1; //拉高时钟信号
}
TRISB4=0; //恢复数据口方向为输出
sclk=0; //拉低时钟信号
return(rx_data); //返回读取到的数据
}
//----------------------------------------------
//写DS1302
void write_ds1302(unsigned char addr,unsigned char code)
{
rst=0;
sclk=0;
rst=1;
write_byte(addr);
write_byte(code);
sclk=0;
rst=1;
}
//-------------------------------------------
//读DS1302
void read_ds1302(unsigned char addr)
{
rst=0;
sclk=0;
rst=1;
write_byte(addr);
read_data=read_byte();
//return read_data;
}
//---------------------------------------------
//读取时间函数
void get_time()
{
int i; //设置循环变量
rst=1; //使能DS1302
write_byte(0xbf); //发送多字节读取命令
for(i=0;i<7;i++) //连续读取7个字节数据
{
table1[i]=read_byte(); //调用读取1个字节数据的函数
}
rst=0; //复位DS1302
}
//DS1302初始化函数
void ds1302_init()
{
sclk=0; //拉低时钟信号
rst =0; //复位DS1302
rst=1; //使能DS1302
write_ds1302(0x8e,0); //发控制命令
rst=0; //复位
}
//---------------------------------------------
//设置时间函数
void set_time()
{
//定义待设置的时间: 秒、 分、 时、 日、月、星期、年、控制字
const char table[]={0x00,0x00,0x12,0x23,0x10,0x05,0x09,0x00};
int i; //定义循环变量
rst=1; //使能DS1302
write_byte(0xbe); //时钟多字节写命令
for(i=0;i<8;i++) //连续写8个字节数据
{
write_byte(table[i]); //调用写一个字节函数
}
rst=0; //复位
}
//-------------------------------------------
//8位二进制数转换为十进制数
void two_to_ten(unsigned char i)
{
time=(table1[i]&0x0f)+(table1[i]>>4)0;
}
//-------------------------------------------
//十进制数转换为BCD码
void ten_to_bcd(unsigned char i)
{
time=((i/0)<<4)|(i%0);
}
//------------------------------------------
//校时程序
void change_time()
{
if(RC0==0) //改变星期---k13
{
delay();
if(RC0==0)
{
if(count==0)
{
count=1;
two_to_ten(5);
week=time;
week++;
if(week>=8)
{
week==1;
write_ds1302(0x8A,1);
}
else
write_ds1302(0x8A,week);
}
}
}
else if(RC1==0) //秒归零--k12
{
delay();
if(RC1==0)
{
if(count==0)
{
count=1;
write_ds1302(0x80,0);
}
}
}
else if(RC2==0) //改变分位--k11
{
delay();
if(RC2==0)
{
if(count==0)
{
count=1;
two_to_ten(1);//BCD码转换成十进制数
min=time;
min++;
if(min>=60)
{
min=0;
write_ds1302(0x82,min);
}
else
{
ten_to_bcd(min);//十进制数转换为BCD码存进DS1302
write_ds1302(0x82,time);
}
}
}
}
else if(RC3==0) //改变小时位--k10
{
delay();
if(RC3==0)
{
if(count==0)
{
count=1;
two_to_ten(2);//BCD码转换成十进制数
hour=time;
hour++;
if(hour>=24)
{
hour=0;
write_ds1302(0x84,hour);
}
else
{
ten_to_bcd(hour);
write_ds1302(0x84,time);
}
}
}
}
else if(RB2==0)
{
delay();
if(RB2==0)
{
if(count==0)
{
count=1;
two_to_ten(4);//BCD码转换成十进制数
mon=time;
mon++;
if(mon>=13)
{
mon=1;
write_ds1302(0x88,mon);
}
else
{
ten_to_bcd(mon);
write_ds1302(0x88,time);
}
}
}
}
else if(RB3==0)
{
delay();
if(RB3==0)
{
if(count==0)
{
count=1;
two_to_ten(3);//BCD码转换成十进制数
day=time;
day++;
if((table1[6]%4==0)&&(table1[4]==2)&&(day>=30)) //润年2月
{
day=1;
write_ds1302(0x86,day);
}
else if(((table1[6]%4)!=0)&&(table1[4]==2)&&(day>=29))//非润年的2月
{
day=1;
write_ds1302(0x86,day);
}
else if(((table1[4]==1)||(table1[4]==3)||(table1[4]==5)||(table1[4]==7)||(table1[4]==8)||(table1[4]==0x10)||(table1[4]==0x12))&&(day>=32))
{
day=1;
write_ds1302(0x86,day);
}
else if(((table1[4]==4)||(table1[4]==6)||(table1[4]==9)||(table1[4]==0x11))&&(day>=31))
{
day=1;
write_ds1302(0x86,day);
}
else
{
ten_to_bcd(day);
write_ds1302(0x86,time);
}
}
}
}
else if(RB1==0)
{
delay();
if(RB1==0)
{
if(count==0)
{
count=1;
two_to_ten(6);//BCD码转换成十进制数
year=time;
year++;
if(year>=16)
{
year=0x00;
write_ds1302(0x8c,0);
}
else
{
ten_to_bcd(year);
write_ds1302(0x8c,time);
}
}
}
}
else
count=0;
}
//
//lcd1602
//
//延时程序
//void delay()
// {
// unsigned char i;
// for(i=100;i>0;i--);
// }
//
//LCD写一个字节数据
void write_lcd(unsigned char code)
{
PORTD=code;
rs=1;
rw=0;
e=0;
delay();
e=1;
}
//
//lcd写命令函数
void lcd_enable(unsigned char code)
{
PORTD=code;
rs=0;
rw=0;
e=0;
delay();
e=1;
}
//
//lcd显示设置
void lcd_init()
{
lcd_enable(0x01); //清除显示
lcd_enable(0x38); //设置16X2显示,5X7点阵
lcd_enable(0x0c); //开显示,不显示光标
lcd_enable(0x06); //光标左移
}
//-------------------------------------------
//显示函数
void display()
{
// PORTD=0X80; //小时
lcd_enable(0X80);
write_lcd((table1[2]>>4)+0x30);
// PORTD=0x81;
lcd_enable(0x81);
write_lcd((table1[2]&0x0f)+0x30);
// PORTD=0X82;
lcd_enable(0X82);
write_lcd(':');
// PORTD=0X83; //分
lcd_enable(0X83);
write_lcd((table1[1]>>4)+0x30);
// PORTD=0x84;
lcd_enable(0x84);
write_lcd((table1[1]&0x0f)+0x30);
// PORTD=0X85;
lcd_enable(0X85);
write_lcd(':');
// PORTD=0X86; //秒
lcd_enable(0X86);
write_lcd((table1[0]>>4)+0x30);
// PORTD=0x87;
lcd_enable(0x87);
write_lcd((table1[0]&0x0f)+0x30);
// PORTD=0X89; //温度的百位
lcd_enable(0X89);
write_lcd(bai);
// PORTD=0X8a; //温度的十位
lcd_enable(0X8a);
write_lcd(shi+0x30);
// PORTD=0X8b; //温度的个位
lcd_enable(0X8b);
write_lcd(ge+0x30);
// PORTD=0X8c;
lcd_enable(0X8c);
write_lcd('');
// PORTD=0X8d; //温度的十分位
lcd_enable(0X8d);
write_lcd(shifen+0x30);
// PORTD=0X8e; //显示'C'
lcd_enable(0X8e);
write_lcd('C');
//
// PORTD=0XC0; //年
lcd_enable(0XC0);
write_lcd((table1[6]>>4)+0x30);
//PORTD=0XC1;
lcd_enable(0XC1);
write_lcd((table1[6]&0x0f)+0x30);
// PORTD=0XC2;
lcd_enable(0XC2);
write_lcd('-');
// PORTD=0XC3; //月
lcd_enable(0XC3);
write_lcd((table1[4]>>4)+0x30);
// PORTD=0xC4;
lcd_enable(0xC4);
write_lcd((table1[4]&0x0f)+0x30);
// PORTD=0XC5;
lcd_enable(0XC5);
write_lcd('-');
// PORTD=0XC6; //日
lcd_enable(0XC6);
write_lcd((table1[3]>>4)+0x30);
// PORTD=0xC7;
lcd_enable(0xC7);
write_lcd((table1[3]&0x0f)+0x30);
// PORTD=0XCD; //星期
lcd_enable(0XCD);
write_lcd((table1[5]&0x0f)+0x30);
}
//--------------------------------------------
//引脚定义函数
void port_init()
{
TRISA=0x00; //设置A口全输出
TRISD=0X00; //设置D口全输出
ADCON1=0X06; //设置A口为普通I/O口
TRISB=0X0E; //
OPTION=0X00; //开启B口弱上拉
PORTA=0XFF;
PORTD=0XFF; //先熄灭所有显示
lcd_init();
TRISC=0XEF; //RC3输出,其他为输入
PORTC=0XEF;
count=0;
}
//----------------------------------------------
//主函数
void main()
{
port_init(); //调用引脚初始化函数
read_ds1302(0x81); //查看DS1302是否起振
if(read_data&0x80) //否,则初始化DS1302
{
ds1302_init(); //调用DS1302初始化函数
set_time(); //调用设置时间函数
}
while(1)
{
get_time(); //调用取时间函数
change_time();
get_temp(); //调用温度转换函数
display(); //调用显示函数
}
}
PIC单片机 同步电动机运行稳定性和可靠性对工业生产有重要的影响。单片机用于同步电动机励磁控制,由于软件丰富,能使励磁装置结构简化、功能增多且易于实现复杂的控制规律,同时还具有参数整定灵活,使用维护方便和故障自诊断功能。目前,国内许多基于单片机的同步电动机励磁控制系统与传统的模拟励磁控制系统相比性能有很大的提高,但因为采用的单片机内部资源较少使得单片机外围电路复杂,其内部控制程序采用查表的方法,这样影响了整个励磁控制系统的精度、快速性和稳定性。PIC16F877单片机内部资源丰富,广泛应用于工业控制领域。我们研制了基于PIC16F877单片机的同步电动机新型智能励磁控制系统,控制程序可以实时计算,利用内部的捕捉单元可以很容易实现自动投励、全压投切电路。同时我们通过控
接上ICD2,然后选debugger,中的select tools中的 MPLAB ICD2,连接上ICD2后,选择debugger菜单中的Read就能把程序读进来。
在VIEW菜单中的Program Memory就能看到程序。读到的是没有宏指令的汇编语句
在程序存储器中只能放置常量,用查表的方式读取数据。这数组跟着程序一起烧写到程序寄存器中。写完程序就不能对其进行修改了(只读的)。因为程序也在程序存储器内,所以程序无法修改自己所在区域的信息。
如果你要 *** 作这数据,只能外扩一个flash芯片。将其作为外扩数据存储器
以上就是关于有几行PIC单片机的c语言程序代码看不懂,请教一下。全部的内容,包括:有几行PIC单片机的c语言程序代码看不懂,请教一下。、求PIC单片机汇编示例程序、最近刚学PIC单片机,有个程序看不懂,请高手帮下,越详细越好:等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)