PIC简单例程
----IIC 模拟- ---
#include "i2c.h"
/******************************************************************************* * 函 数 名 : Delay1us() * 函数功能 : 延时 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/
void I2C_Delay10us () { uchar a, b; for (b= 10 ; b> 0 ; b--) { for (a= 5 ; a> 0 ; a--); } } /******************************************************************************* * 函 数 名 : I2C_Start() * 函数功能 : 起始信号:在I2C_SCL时钟信号在高电平期间I2C_SDA信号产生一个下降沿 * 输 入 : 无 * 输 出 : 无 * 备 注 : 起始之后I2C_SDA和I2C_SCL都为0 *******************************************************************************/
void I2C_Start () { TRISB0= 0 ; TRISB1= 0 ; I2C_SCL= 1 ; I2C_SDA = 0 ; I2C_Delay10us (); I2C_SDA = 1 ; I2C_Delay10us (); I2C_SDA = 0 ; I2C_SCL= 0 ; } /******************************************************************************* * 函 数 名 : I2C_Stop() * 函数功能 : 终止信号:在I2C_SCL时钟信号高电平期间I2C_SDA信号产生一个上升沿 * 输 入 : 无 * 输 出 : 无 * 备 注 : 结束之后保持I2C_SDA和I2C_SCL都为1;表示总线空闲 *******************************************************************************/
void I2C_Stop () { TRISB0= 0 ; TRISB1= 0 ; I2C_SCL = 0 ; I2C_SDA = 0 ; I2C_Delay10us (); I2C_SCL = 1 ; I2C_Delay10us (); I2C_SDA = 1 ; I2C_Delay10us (); I2C_SDA = 0 ; } /******************************************************************************* * 函 数 名 : I2cSendByte(uchar num) * 函数功能 : 通过I2C发送一个字节。在I2C_SCL时钟信号高电平期间, * * 保持发送信号I2C_SDA保持稳定 * 输 入 : num ,ack * 输 出 : 0或1。发送成功返回1,发送失败返回0 * 备 注 : 发送完一个字节I2C_SCL=0, 需要应答则应答设置为1,否则为0 *******************************************************************************/ uchar I2C_SendByte (uchar dat , uchar ack ) { TRISB0= 0 ; TRISB1= 0 ; uchar i,b; for (i= 0 ;i< 8 ;i++) { I2C_SDA= dat >> 7 ; //因为从最高位开始 dat = dat << 1 ; //把最高位变成次高位 I2C_SCL= 0 ; I2C_Delay10us (); I2C_SCL= 1 ; I2C_Delay10us (); I2C_SCL= 0 ; }
I2C_SDA = 1 ; I2C_Delay10us (); TRISB1= 1 ; I2C_SCL = 1 ; while (I2C_SDA && ( ack == 1 )) //等待应答,也就是等待从设备把I2C_SDA拉低 { b++; if (b > 200 ) //如果超过200us没有应答发送失败,或者为非应答,表示接收结束 { I2C_SCL = 0 ; I2C_Delay10us (); return 0 ; } } I2C_SCL= 0 ; I2C_Delay10us (); TRISB0= 0 ; TRISB1= 0 ; return 1 ; //初始化成功返还1
} /******************************************************************************* * 函 数 名 : I2cReadByte() * 函数功能 : 使用I2c读取一个字节 * 输 入 : 无 * 输 出 : dat * 备 注 : 接收完一个字节I2C_SCL=0 *******************************************************************************/ uchar I2C_ReadByte () { TRISB0= 0 ; TRISB1= 0 ; uchar a,dat= 0 ; //a来执行循环 dat用来接收数据 I2C_SDA= 1 ; //接收数据 因为数据是拉低的 要是置0的话 那就没办法接受1 I2C_Delay10us (); //让数据稳定的 for (a= 0 ;a< 8 ;a++) { TRISB1= 1 ; I2C_SCL = 0 ; I2C_Delay10us (); dat=dat<< 1 ; //方便下次接收 dat|=I2C_SDA; I2C_Delay10us (); I2C_SCL = 1 ; I2C_Delay10us (); } TRISB1= 0 ; TRISB0= 0 ; return dat; }
#ifndef __I2C_H_ #define __I2C_H_
#include
//---重定义关键词---// #ifndef uchar #define uchar unsigned char #endif
#ifndef uint #define uint unsigned int #endif
//--定义使用的IO口--// #define I2C_SCL RB0 #define I2C_SDA RB1
//--声明全局变量--// void I2C_Delay10us (); void I2C_Start (); void I2C_Stop (); uchar I2C_SendByte ( uchar dat , uchar ack ); uchar I2C_ReadByte ();
#endif
|
- --- 24X xx使用 ---
void At24c02Write (uchar addr ,uchar dat ) { I2C_Start (); I2C_SendByte ( 0xa0 , 1 ); //发送写器件地址 I2C_SendByte ( addr , 1 ); //发送要写入内存地址 I2C_SendByte ( dat , 0 ); //发送数据 I2C_Stop (); } /******************************************************************************* * 函 数 名 : unsigned char At24c02Read(unsigned char addr) * 函数功能 : 读取24c02的一个地址的一个数据 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/
uchar At24c02Read (uchar addr ) { uchar num ; I2C_Start (); I2C_SendByte ( 0xa0 , 1 ); //发送写器件地址 I2C_SendByte ( addr , 1 ); //发送要写入内存地址 I2C_Start (); I2C_SendByte ( 0xa1 , 0 ); //发送写器件地址 num = I2C_ReadByte (); //读取数据 I2C_Stop (); //读取完毕 return num ; //返还num }
|
- ---TLC2543 驱动 ----
#include
//#include"lcd.h" #include "stdio.h" #include "HELLOPIC.h" #define CS RB2 #define CLK RB3 #define SDI RB1 #define SDO RB0 int Read_TLC2543 (uchar chnal ); void main () { int h ; TRISB0= 1 ; //设置RB0为输入端口 TRISB1= 0 ; //设置RB为输出端口 TRISB2= 0 ; //设置RB为输出端口 TRISB3= 0 ; //设置RB为输出端口 TRISC= 0X00 ; while ( 1 ) { h = Read_TLC2543 ( 0x0a ); //选择通道还有一定的问题 h = h >> 4 ; PORTC= h ; delayms ( 10 ); } } int Read_TLC2543 (uchar chnal ) //设置通道 { int ADC_Value ; uchar i ; CLK = 0 ; //时钟位置0 CS = 1 ; // 片选置0 开始转换 NOP (); NOP (); NOP (); //延时几个us让数据稳定下来 CS = 0 ; //开始转换 for ( i = 0 ; i < 8 ; i ++) { CLK = 1 ; if (( chnal & 0x80 )!= 0 ) { SDI = 1 ; //将数据写入芯片 chnal = chnal <<= 1 ; //将最低位晚上左移一位 } else { SDI = 0 ; chnal = chnal <<= 1 ; //将最低位晚上左移一位 } CLK = 0 ; if ( SDO ) //当输出高电平信号时 { ADC_Value = ADC_Value | 0x0001 ; //接收到高电平最后一位+1 } ADC_Value = ADC_Value <<= 1 ; //时钟来一次数据更新一次
} SDI = 0 ; for ( i = 0 ; i < 4 ; i ++) { if ( SDO ) //当输出高电平信号时 { ADC_Value = ADC_Value | 0x0001 ; //接收到高电平最后一位+1 } ADC_Value = ADC_Value <<= 1 ; //时钟来一次数据更新一次 CLK = 1 ; CLK = 0 ; } CS = 1 ; //关闭片选 return ADC_Value ; }
|
- --- 数字电压表 ----
#include
#include "stdio.h" #include "lcd.h" #include "HELLOPIC.h" uchar tab [ 30 ]; void displaywc (); void adc_show (); void main () { TRISC= 0x00 ; //设置pwm脚为输出模式 init (); lcd_init (); ADC_Config (); while ( 1 ) { adc_show (); displaywc (); } } void adc_show () { int i , J ; J = getadc (); J =( J / 5.1 ); sprintf ( tab , "voltageprice: %02d" , J ); PORTB = 0X80 ; //从第一行第一个开始 lcd_enable (); for ( i = 0 ; i < 16 ; i ++) { write ( tab [ i ]); } } void displaywc () { uchar i ; const uchar welcome [] ={ " digital volta " }; PORTB = 0X80 + 0X40 ; //从第一行第一个开始 lcd_enable (); for ( i = 0 ; i < 16 ; i ++) { write ( welcome [ i ]); } }
|
- ---PWM 定时器- ---
#include
#include "HELLOPIC.h" void main () { TRISC= 0X00 ; TRISB= 0X00 ; TRISA= 0X00 ; Timer0_Config (); Timer1_Config (); Timer2_Config (); while ( 1 ) { delayms ( 5 ); } } void interrupt timer () { if (TMR2IF== 1 ) { TMR2= 0x00 ; TMR2IF= 0 ; RB0=~RB0; } if (TMR1IF== 1 ) { TMR1H=( 65535 - 5000 )/ 256 ; TMR1L=( 65535 - 5000 )% 256 ; TMR1IF= 0 ; RB1=~RB1; } if (TMR0IF== 1 ) { TMR0= 0x00 ; TMR0IF= 0 ; RB2=~RB2; } }
|
- --- 黑喂狗- ---
#include
#include "MAIN.h" __CONFIG (LVPDIS & HS & PWRTDIS & BORDIS ); //设置配置位,使能看门狗 void main () { TRISD= 0X00 ; PORTD= 0XFF ; delayms ( 500 ); while ( 1 ) { PORTD= 0X00 ; delayms ( 300 ); asm ( "clrwdt" ); //喂狗
} }
|
- ---CCP 捕捉- ---
#include
#define uchar unsigned char #define uint unsigned int #define s2 RA0 #define S3 RA1 __CONFIG ( 0xFF32 ); void usart_Config () { TRISC= 0XFF ; //设置C口方向全为输出 SPBRG= 0XC ; //设置波特率为119200BPS TXSTA= 0X24 ; //使能串口发送,选择高速波特率 RCSTA= 0X90 ; //使能串口工作,连续接收 RCIE= 0X1 ; //使能接收中断 } void CCP_Config () { //设置RC2为输入 CCP1CON= 0X05 ; //首先设置CCP1捕捉每个脉冲的上升沿 T1CON= 0X01 ; //关闭TMR1震荡器 PEIE= 1 ; //外围中断允许(此时总中断关闭) PIE1= 0x05 ; CCP1IF= 0 ; TRISC2= 1 ; CCPR1H= 0 ; CCPR1L= 0 ; } void delay () { int i; for (;i< 30000 ;i++); } void main () { TRISA= 0xfc ; //使能s2 s3引脚 设置其他脚为接收脚 TRISD= 0x00 ; usart_Config (); CCP_Config (); int j; while ( 1 ) { delay (); delay (); } }
void interrupt zhonduan ( void ) { /* if(RCIE&&RCIF) //判断是否为串口接收中断 { TXREG=RCREG; //把接收到的数据发送回去 }*/ if (CCP1IF== 1 ) { TXREG=CCPR1H+ '0' ; delay (); delay (); delay (); delay (); } }
|
- --- 外部中断- ---
#include
#define uchar unsigned char #define uint unsigned int uint x ; void init () //初始化中断 以及端口 { // OPTION=0x33; INTCON= 0xb0 ; TRISA= 0x10 ; TRISD= 0x00 ; TRISB= 0x01 ;
} void main () {
init (); while ( 1 ); } void interrupt time0 () { INTF= 0 ; // TMR0=253; //定时器装初值 PORTD=~PORTD; }
|
- --- 串口- ---
#include
__CONFIG ( 0xFF32 ); //芯片配置字,看门狗关,上电延时开,掉电检测关,低压编程关,加密,4M晶体HS振荡
/**************************************************************************** * 名 称:main() * 功 能:主函数 * 入口参数:无 * 出口参数:无 * 说 明:无 ****************************************************************************/ void main () { TRISC= 0XFF ; //设置C口方向全为输出 SPBRG= 0XC ; //设置波特率为119200BPS TXSTA= 0X24 ; //使能串口发送,选择高速波特率 RCSTA= 0X90 ; //使能串口工作,连续接收 RCIE= 0X1 ; //使能接收中断 GIE= 0X1 ; //开放全局中断 PEIE= 0X1 ; //使能外部中断 while ( 1 ) //等待中断 {;} } /**************************************************************************** * 名 称: usart() * 功 能:中断函数 * 入口参数: * 出口参数: * 说 明:注意要有关键字 interrupt 如果是多种中断,在中断服务函数中, 要判断中断源标志 ****************************************************************************/ void interrupt usart ( void ) { if (RCIE&&RCIF) //判断是否为串口接收中断 { TXREG=RCREG; //把接收到的数据发送回去 } }
|
- ---ADC----
#include
#define uchar unsigned char #define uint unsigned int void init () { int i; TRISA= 0X01 ; //将RA0设置为模拟量输入端口 TRISD= 0x00 ; PORTA= 0X00 ; PORTD= 0X00 ; ADCON0= 0x41 ; //选择通道0 选择分频 频率2us 开启adc电源 ADCON1= 0x8e ; //只有 ra0是模拟量输入 i= 1000 ; while (i--); } uint getadc () { uint leve; ADGO= 1 ; //开启ad转换 while (ADGO) //等待ad转换完成 leve=ADRESL; //将adc的值给leve PORTD=leve; //显示leve的值 } void main () { init (); while ( 1 ) {
getadc (); } }
|
- --- 电子密码锁- ---
#include
#include "lcd.h" uchar x , x1 , x2 , s1 , s2 , s3 , s4 ; void displaywc (); void displayps (); uchar key (); void writekey (); void seekey (); void main () { init (); //调用I/O口初始化函数 lcd_init (); displaywc (); while ( 1 ) { key (); x1 = x ; while ( x1 ) { displayps (); x1 = 1 ; x = 0 ; writekey ();
} } /* write('a'); PORTD = 0XC0; //设置第2行显示地址 lcd_enable(); //调用LCD显示设置函数 write('a');*/ } /***************写入密码***********************/ void writekey () { x = 0 ; key (); while (! key ()); s1 = x ; PORTD = 0X80 + 0x40 ; //从第一行第一个开始 lcd_enable (); write ( '0' + s1 ); x = 0 ; key (); while (! key ()); s2 = x ; PORTD = 0X80 + 0x41 ; //从第一行第一个开始 lcd_enable (); write ( '0' + s2 ); x = 0 ; key (); while (! key ()); s3 = x ; PORTD = 0X80 + 0x43 ; //从第一行第一个开始 lcd_enable (); write ( '0' + s3 ); x = 0 ; key (); while (! key ()); s4 = x ; PORTD = 0X80 + 0x44 ; //从第一行第一个开始 lcd_enable (); write ( '0' + s4 ); x = 0 ; seekey (); } /**************密码正确错误检测***************/ void seekey () { while (!( s1 == 1 )); while (!( s2 == 2 )); while (!( s3 == 3 )); while (!( s4 == 4 )); displaywc (); while ( 1 );
} /**************显示输入密码********************/ void displayps () { uchar i ; const uchar prd [] ={ "pass word write " }; PORTD = 0X80 ; //从第一行第一个开始 lcd_enable (); for ( i = 0 ; i < 16 ; i ++) { write ( prd [ i ]); } } /*********************显示欢迎函数************************/ void displaywc () { uchar i ; const uchar welcome [] ={ " welcome back " }; PORTD = 0X80 ; //从第一行第一个开始 lcd_enable (); for ( i = 0 ; i < 16 ; i ++) { write ( welcome [ i ]); } } /*******************按键函数**************************/ uchar key () { TRISB= 0X0f ; //选择行为输入列为输出 PORTB= 0X00 ; //列输出0行检测 if (RB0== 0 ) { delay ( 10 ); if (RB0== 0 ) { TRISB= 0Xf0 ; PORTB= 0X00 ; { if (RB4== 0 ) { while (!RB4); x = 1 ; } if (RB5== 0 ) { while (!RB5); x = 2 ; } if (RB6== 0 ) { while (!RB6); x = 3 ; } if (RB7== 0 ) { while (!RB7); x = 4 ; } }
} } if (RB1== 0 ) { delay ( 10 ); if (RB1== 0 ) { TRISB= 0Xf0 ; PORTB= 0X00 ; { if (RB4== 0 ) { while (!RB4); x = 5 ; } if (RB5== 0 ) { while (!RB5); x = 6 ; } if (RB6== 0 ) { while (!RB6); x = 7 ; } if (RB7== 0 ) { while (!RB7); x = 8 ; }
}
} } if (RB2== 0 ) { delay ( 10 ); if (RB2== 0 ) { TRISB= 0Xf0 ; PORTB= 0X00 ; { if (RB4== 0 ) { while (!RB4); x = 9 ; } if (RB5== 0 ) { while (!RB5); x = 10 ; } if (RB6== 0 ) { while (!RB6); x = 11 ; } if (RB7== 0 ) { while (!RB7); x = 12 ; } } } } if (RB3== 0 ) { delay ( 10 ); if (RB3== 0 ) { TRISB= 0Xf0 ; PORTB= 0X00 ; { if (RB4== 0 ) { while (!RB4); x = 13 ; } if (RB5== 0 ) { while (!RB5); x = 14 ; } if (RB6== 0 ) { while (!RB6); x = 15 ; } if (RB7== 0 ) { while (!RB7); x = 16 ; }
} } } return x ; }
|
----LCD1602----
#include
#include "lcd.h" void main () {
init (); //调用I/O口初始化函数 lcd_init ();
write ( 'a' ); PORTD = 0XC0 ; //设置第2行显示地址 lcd_enable (); //调用LCD显示设置函数 write ( 'a' ); while ( 1 );
}
lcd .c
#include "lcd.h" void init () { ADCON1 = 0X07 ; //设置A口为普通I/O口 RA1= 1 ; TRISA = 0X00 ; //设置A口为输出 TRISD = 0X00 ; //设置D口为输出 }
void lcd_init () { PORTD = 0X1 ; //清除显示 lcd_enable (); PORTD = 0X38 ; //8位2行5*7点阵 lcd_enable (); PORTD = 0X0c ; //显示开,光标开,闪烁 lcd_enable (); PORTD = 0X06 ; //文字不动,光标右移 lcd_enable (); PORTD = 0X80 ; //公司web显示地址 lcd_enable (); } void write ( char x ) { PORTD = x; //待显示数据送PORTD口 rs = 1 ; //该字节数据为数据,而不是命令 rw = 0 ; //此次操作为写,而不是读 e = 0 ; //拉低使能信号 delay (); //保持使能信号为低一段时间 e = 1 ; //拉高使能信号,建立LCD操作所需要的上升沿 } void lcd_enable () { rs = 0 ; //该字节数据为命令,而不是数据 rw = 0 ; //此次操作为写,而不是读 e = 0 ; //拉低使能信号 delay (); //保持使能信号为低一段时间 e = 1 ; //拉高使能信号,建立LCD操作所需要的上升沿 } void delay () { int i; for (i = 0 ;i < 5000 ;i++);}
lcd.h
#ifndef __lcd_H #define __lcd_H
/********************************** 包含头文件 **********************************/
#include
//---重定义关键词--- #ifndef uchar #define uchar unsigned char #endif
#ifndef uint #define uint unsigned int #endif /********************************** PIN口定义 **********************************/ #define rs RA5 #define rw RA4 #define e RA3 /********************************** 函数声明 **********************************/ void init (); //申明I/O口初始化函数 void lcd_init (); //申明LCD初始化函数 void write ( char x ); //申明显示1字节数据函数 void lcd_enable (); //申明LCD显示设置函数 void delay (); //申明延时函数 void wcmd ( char cmd ); //写指令 #endif
|
- --- 数码管- ---
#include
#define uchar unsigned char #define uint unsigned int uchar shu [] ={ 0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 , 0x08 }; void delay (); void main () { uchar i; TRISD= 0x00 ; //设置成输出端口 TRISB= 0x00 ; //设置成输出端口 while ( 1 ) { delay (); delay (); delay (); PORTB= shu [i]; delay (); delay (); delay (); i++; if (i== 9 )i= 0 ; } } void delay () { int i; //定义整形变量 for (i = 10000 ;i--;); //延时 }
数码管动态显示
#include
#define uchar unsigned char #define uint unsigned int uchar shu [] ={ 0xc0 , 0xf9 , 0xa4 , 0xb0 , 0x99 , 0x92 , 0x82 , 0xf8 , 0x80 , 0x90 , 0x88 , 0x83 , 0xc6 , 0xa1 , 0x86 , 0x8e }; void delay (); void main () { uchar i; TRISD= 0x00 ; //设置成输出端口 TRISB= 0x00 ; //设置成输出端口 while ( 1 ) {
for (i= 0 ;i< 9 ;i++) { PORTD= 0X01 ; PORTD=PORTD< PORTD=~PORTD; PORTB= shu [i]; delay ();
} } } void delay () { int i; //定义整形变量 for (i = 10000 ;i--;); //延时 }
|
- --- 点灯- ---
#include
#define uchar unsigned char #define uint unsigned int void delay (); void main () { TRISD= 0x00 ; //设置成输出端口 while ( 1 ) { delay (); delay (); PORTD= 0XFF ; delay (); delay (); } } void delay () { int i; //定义整形变量 for (i = 10000 ;i--;); //延时 }
|
也算是咱们家电行业资深工程师了~
唯一的遗憾是没有玩过1块钱以下的 .
邮箱xutong @ zjbtie .com