‘壹’ 在pic中如何用C语言编写程序
//09/10/24
//lcd1602显示时间 日期 星期 温度
//通过按键校时:K10--小时,K11--分钟,K12--秒(归零),K13-星期,BR1--年,RB2--月,RB3--日。
//芯片要求:PIC16F877A
#include<pic.h> //包含单片机内部资源预定义
__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 ;
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)*0.0625*10+0.5; //负温度时,取反加1再乘以0.0625得实际温度,乘10+0.5显示小数点一位,且四舍五入
}
else
temp=t*0.0625*10+0.5; //正温度
if(t<0)
='-'; //负温度时百位显示负号
else
=(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)*0x0a;
}
//-------------------------------------------
//十进制数转换为BCD码
void ten_to_bcd(unsigned char i)
{
time=((i/0x0a)<<4)|(i%0x0a);
}
//------------------------------------------
//校时程序
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();
// 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单片机c语言中如何喂狗
首先你要说明你用的是哪款PIC的单片机和用哪个C编译器。
PIC有中低端的八位单片机PIC10/12/16的,高端的八位单片机PIC18系列,1十六位单片机PIC24和dsPIC,还有一个PIC32是三十二位的。上述的都可以通过调用宏指令CLRWDT();来实现喂狗。
但他们的宏指令的声明一般都是在各自的头文件中,比如根据他们的数据手册PIC10/12/16系列的宏指令声明都在htc.h文件中,pic.h里我还没试过。
而PIC18我用过的是MPLAB C18编译器,其声明宏指令的头文件是这个芯片的名称,如PIC18F4680.h。
而PIC24我用的是MPLAB C30编译器我是直接根据数据手册的要求在C文件里定义宏的:
#define ClrWdt() {__asm__ volatile ("clrwdt");}
而前面的八位单片机的C语言也可以用下列嵌入汇编的方法: asm("CLRWDT");
‘叁’ pic系列单片机用c语言编程时,让他执行A/D转换的指令是什么
AD转换不是一条指令就可以完成的,它要先经过端口设置,AD设置等过程后才能准备进入AD转换,下例是从北航的<PIC16单片机C程序设计与PROTEUS仿真>一书中得到的启发编制的程序,希望对你能有帮助.建议你看一下这本书,对初学和想进一步提高在PIC单片机应用编程等会有用的.
附图是对应程序的,在仿真时调整电位器可以看到AD结果的变化,并通过计算器可以验证程序的正确性.
//ADl转换示例,可以改变输入电压、AD通道、结果对齐方式等,看其变化
#include<pic.h>
__CONFIG(0x3F39);//配置位设置
voidmain(void)
{ chari,X,Y;
TRISA=0xFF; //将所有的A口设置为输入
TRISE=0x03; //将所有的E口设置为输入
TRISD=0; //C口与D口全为输出
TRISC=0;
ADCON1=0b10000000; //设置AD结果对齐方式、AD时钟选择(与ADCON0的位7,6一起),AD端口设置等
ADCON0=0b01011001; //AD时钟选择(与ADCON1的位6一起),通道选择,AD模块使能
while(1)
{ NOP();
for(i=0;i<3;i++) //延时时间大约20us
NOP();
ADGO=1; //开始AD
while(ADGO==1); //等待AD转换完成
ADIF=0;
X=ADRESH; //读取AD结果高字节至C口
PORTC=X;
Y=ADRESL; //读取AD结果低字节至D口
PORTD=Y;
};
}
‘肆’ 单片机C语言程序设计实训100例:基于PIC+Proteus仿真的目录
第1章PIC单片机C语言程序设计概述
1.1 PIC单片机简介
1.2 MPLAB+C语言程序开发环境安装及应用
1.3 PICC/PICC18/MCC18程序设计基础
1.4 PIC单片机内存结构
1.5 PIC单片机配置位
1.6 基本的I/O端口编程
1.7 中断服务程序设计
1.8 PIC单片机外设相关寄存器
1.9 C语言程序设计在PIC单片机应用系统开发中的优势
第2章PROTEUS操作基础
2.1 PROTEUS操作界面简介
2.2 仿真电路原理图设计
2.3 元件选择
2.4 仿真运行
2.5 MPLAB IDE与PROTEUS的联合调试
2.6 PROTEUS在PIC单片机应用系统开发中的优势
第3章 基础程序设计
3.1 闪烁的LED
3.2 用双重循环控制LED左右来回滚动显示
3.3 多花样流水灯
3.4 LED模拟交通灯
3.5 单只数码管循环显示0~9
3.6 4只数码管滚动显示单个数字
3.7 8只数码管扫描显示多个不同字符
3.8 K1~K5控制两位数码管的开关、加减与清零操作
3.9 数码管显示4×4键盘矩阵按键
3.10 数码管显示拨码开关编码
3.11 继电器及双向可控硅控制照明设备
3.12 INT中断计数
3.13 RB端口电平变化中断控制两位数码管开关与加减显示
3.14 TIMER0控制单只LED闪烁
3.15 TIMER0控制流水灯
3.16 TIMER0控制数码管扫描显示
3.17 TIMER1控制交通指示灯
3.18 TIMER1与TIMER2控制十字路口秒计时显示屏
3.19 用工作于同步计数方式的TMR1实现按键或脉冲计数
3.20 用定时器设计的门铃
3.21 报警器与旋转灯
3.22 用工作于捕获方式的CCP1设计的频率计
3.23 用工作于比较模式的CCP1控制音阶播放
3.24 CCP1 PWM模式应用
3.25 模拟比较器测试
3.26 数码管显示两路A/D转换结果
3.27 EEPROM读写与数码管显示
3.28 睡眠模式及看门狗应用测试
3.29 单片机与PC双向串口通信仿真
3.30 PIC单片机并行从动端口PSP读写测试
第4章 硬件应用
4.1 74HC138与74HC154译码器应用
4.2 74HC595串入并出芯片应用
4.3 用74HC164驱动多只数码管显示
4.4 数码管BCD解码驱动器7447与4511应用
4.5 8×8LED点阵屏显示数字
4.6 8位数码管段位复用串行驱动芯片MAX6951应用
4.7 串行共阴显示驱动器MAX7219与7221应用
4.8 14段与16段数码管串行驱动显示
4.9 16键解码芯片74C922应用
4.10 1602LCD字符液晶测试程序
4.11 1602液晶显示DS1302实时时钟
4.12 1602液晶工作于4位模式实时显示当前时间
4.13 带RAM内存的实时时钟与日历芯片PCF8583应用
4.14 2×20串行字符液晶演示
4.15 LGM12864液晶显示程序
4.16 PG160128A液晶图文演示
4.17 TG126410液晶串行模式显示
4.18 HDG12864系列液晶演示
4.19 Nokia7110液晶菜单控制程序
4.20 8通道模拟开关74HC4051应用测试
4.21 用带I2C接口的MCP23016扩展16位通用I/O端口
4.22 用带SPI接口的MCP23S17扩展16位通用I/O端口
4.23 用I2C接口控制MAX6953驱动4片5×7点阵显示器
4.24 用I2C接口控制MAX6955驱动16段数码管显示
4.25 用带SPI接口的数/模转换器MCP4921生成正弦波形
4.26 用带SPI接口的数/模转换器MAX515控制LED亮度循环变化
4.27 正反转可控的直流电机
4.28 PWM控制MOSFET搭建的H桥电路驱动直流电机运行
4.29 正反转可控的步进电机
4.30 用L297+L298控制与驱动步进电机
4.31 PC通过RS-485器件MAX487远程控制单片机
4.32 I2C接口DS1621温度传感器测试
4.33 SPI接口温度传感器TC72应用测试
4.34 温度传感器LM35全量程应用测试
4.35 K型热电偶温度计
4.36 用铂电阻温度传感器PT100设计的测温系统
4.37 DS18B20温度传感器测试
4.38 SHT75温湿度传感器测试
4.39 1-Wire式可寻址开关DS2405应用测试
4.40 光敏电阻应用测试
4.41 MPX4250压力传感器测试
4.42 用I2C接口读写存储器AT24C04
4.43 用SPI接口读写AT25F1024
4.44 PIC18 I2C接口存储器及USART接口测试程序
4.45 PIC18 SPI接口存储器测试程序
4.46 PIC18定时器及A/D转换测试
4.47 用PIC18控制Microwire接口继电器驱动器MAX4820
4.48 MMC存储卡测试
4.49 ATA硬盘数据访问
4.50 微芯VLS5573液晶显示屏驱动器演示
第5章 综合设计
5.1 用DS1302/DS18B20+MAX6951设计的多功能电子日历牌
5.2 用PCF8583设计高仿真数码管电子钟
5.3 用4×20LCD与DS18B20设计的单总线多点温度监测系统
5.4 用内置EEPROM与1602液晶设计的加密电子密码锁
5.5 用PIC单片机与1601LCD设计的计算器
5.6 电子秤仿真设计
5.7 数码管显示的GP2D12仿真测距警报器
5.8 GPS全球定位系统仿真
5.9 能接收串口信息的带中英文硬字库的80×16点阵显示屏
5.10 用M145026与M145027设计的无线收发系统
5.11 红外遥控收发仿真
5.12 交流电压检测与数字显示仿真
5.13 带位置感应器的直流无刷电机PMW控制仿真
5.14 3端可调正稳压器LM317应用测试
5.15 模拟射击训练游戏
5.16 带触摸屏的国际象棋游戏仿真
5.17 温室监控系统仿真
5.18 PIC单片机MODBUS总线通信仿真
5.19 PIC单片机内置CAN总线通信仿真
5.20 基于PIC18+Microchip TCP/IP协议栈的HTTP服务器应用
参考文献
‘伍’ PIC单片机输出PWM波的C语言源程序
#ifndef __PWM__H__
#define __PWM__H__
void pwm_ccp1(unsigned char a,unsigned char b);
void pwm_ccp2(unsigned char a,unsigned char b);
#endif
void pwm_ccp1(unsigned char a,unsigned char b) //左边PWM
//CCP1 模块的 PWM 工作方式,周期为(b+1)*4*Tosc*(TMR2前分频值)=b+1 us //pwm高电平=a:CCP1CON(第四五位)Tosc*(TMR2前分频值)
//pwm高电平=a:CCP1CON(第四五位)Tosc*(TMR2前分频值)
{ //a>b时有最高转速
CCPR1L=a; //* 设置工作循环的高 8bit 为 a
CCP1CON=0X0C; //0000 1100 设置 CCP1 为 PWM 工作方式,且工作循环的低 bit2 为 11*/
CCP1IE=0;; //* 禁止总中断和外围中断 */
PR2=b; //* 设置 PWM 周期 */
TRISC2=0; //* 设置 RC2/CCP1 为输出 */
T2CON=0X04; //* 0000 1000前分频比为 1:1 ,后分频器1:2,打开 TMR2 ,同时输出 PWM 信号 */
}
void pwm_ccp2(unsigned char a,unsigned char b) //右边PWM
//CCP2 模块的 PWM 工作方式,周期为(b+1)*4*Tosc*(TMR2前分频值),
//pwm高电平=a:CCP2CON(第四五位)Tosc*(TMR2前分频值)
{
CCPR2L=a; //* 设置工作循环的高 8bit 为 a
CCP2CON=0X0C; //* 设置 CCP2 为 PWM 工作方式,且工作循环的低 bit2 为 11*/
CCP2IE=0; //* 中断屏蔽
PR2=b; //* 设置 PWM 周期 */
TRISC1=0; //* 设置 RC1/CCP2 为输出 */
T2CON=0X04; //* 前分频比为 1 ,打开 TMR2 ,同时输出 PWM 信号 */
}
‘陆’ 最近刚学PIC单片机,有个程序看不懂,请高手帮下,越详细越好:
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。
‘柒’ 关于PIC单片机C语言编程 MPLAB和PICC的问题
1、新建工程向导里会询问使用哪种编译器. 选择PICC就可以了. 如果没找到PICC那需要在 Project 菜单最后一行 选择语言 里手动设置语言. 另外最好把PICC和MAPLAB安装在同一个目录下。
2、先安装MPLAB7.51和PICC,做好安装在同一目录下,MPLAB会自动进行关联设置,否则需人工干预,在MPLAB顶上 Project 菜单最后一行‘选择语言’里手动设置语言。