pic单片机16F877与spi接口的eeprom读写C程序
PIC16F877编程ICC实例
void main()
{
port_init();
timer0_init();
while(1)
{
display(c);
}
}
}
void port_init()
{
TRISB=0X00;//b口全部为输出
PORTB=0xfF;//初始化为高电平
SC=0X00;//C口全部为输出
PORTC=0xFF;//初始化为高电平
}
void timer0_init()//做开发板的人用的多,加参数
{
T0CS=0;//t0定时模式,位操作
pic16f877pic16f877中文资料pic16f877价格数控编程实例数控铣床编程实例plc编程实例数控车床编程实例c语言编程实例三菱plc编程实例excel编程实例
ICC877IO口程序注解,请大家参考
//877B口操作,定时器控制
#include<pic.h>
#define uchar unsigned char
RC3=0;
PORTB=0x00;
RC2=1;
PORTB=dm[b];
delay(1);
RC2=0;
PORTB=0x00;
RC1=1;
PORTB=dm[s];
delay(1);
RC1=0;
PORTB=0x00;
RC0=1;
PORTB=dm[g];
delay(1);
RC0=0;//0关闭数码管
PORTB=0x00;
{
TMR0=6;//及时给初值
TMR0IF=0;
m++;
if(m>=128)
{
m=0;
PIC16F877 MSSP模块之SPI通信
PIC16F877 MSSP 模块之SPI 通信SPI 模式允许同时、同步发送和接收8 位数据。
支持SPI 的所有四种模式。
一般用以下三个引脚来完成通信:串行数据输出(SDO) 串行数据输入(SDI) 串行时钟(SCK)当工作在从动模式时,可能还需要第4 个引脚:从动选择(SS)结构框图:SSP 模块由一个发送/接收移位寄存器(SSPSR)和一个缓冲寄存器(SSPBUF)组成。
SSPSR 用于器件输入和输出数据的移位,高位在前。
在新的数据接收完毕前,SSPBUF 保存上次写入SSPSR 的数据。
一旦8 位新数据接收完毕,该字节被送入SSPBUF 寄存器。
同时缓冲区满标志位BF(SSPSTAT )和中断标志位SSPIF 置1。
这种双重缓冲接收方式,允许接收数据被读走之前,开始接收下一个数据。
在数据发送/接收期间,任何试图写SSPBUF 寄存器的操作都无效,却会将写冲突检测位WCOL(SSPCON)置1。
此时用户必须用软件将WCOL 位清零,以判别下一次对SSPBUF 的写操作是否成功完成。
为确保应用软件有效地接收数据,应该在新数据写入SSPBUF 之前,将SSPBUF 中的数据读走。
缓冲区满标志位BF(SSPSTAT)用于表示SSPBUF 是否已经载入了接收的数据(发送完成)。
当SSPBUF 中的数据被读取后,BF 位即被清零。
如果SPI 仅仅作为一个发送器,则不必理会这一位。
通常可用SSP 中断来判断发送或接收是否完成。
如果需要接收数据,可从SSPBUF 中读取。
SSP 中断一般用来确定发送/接收何时完成。
必须对SSPBUF 进行读和/写。
如果不打算使用中断方法,用软件查询方法同样可确保不会发生写冲突。
主控模式的操作因为主控制器控制着SCK 信号,所以它可以在任何时候启。
PIC16F877 EEPROM读写实验
PIC16F877 EEPROM每一个单元的读/写所用时间典型值为:4ms,最大值为8ms。
在烧写每个EEPROM 单元过程中,需要CPU插入等待时间,既可利用中断功能,也可利用软件查询方式来解决。
在此我们利用了软件查询方式,循环检测WR烧写控制位兼烧写完成标志位。
程序如下:;实战《16F877内部EEPROM读/写实验》;本实战的目的是让大家熟悉PIC16F87X内部EEPROM的读/写方法;项目实现的功能:对于地址为00H-3FH的64个EEPROM数据存储单元,分;别将数据0-63依次烧写进去,然后再循环读出,显示在LED数码管上;程序清单如下:;************************************INCLUDE"P16F877.INC"STATUS EQU 3H ;定义状态寄存器地址RP0 EQU 5H ;定义页选位RP0的位地址RP1 EQU 6H ;定义页选位RP1的位地址Z EQU 2H ;定义0状态位的位地址PORTC EQU 7H ;定义RC口数据寄存器地址PORTD EQU 8HTRISC EQU 87H ;定义RC口方向控制寄存器地址TRISD EQU 88HEECON1 EQU 18CH ;定义写控制寄存器1的地址EECON2 EQU 18DH ;定义写控制寄存器2的地址EEDATA EQU 10CH ;定义读/写数据寄存器地址EEADR EQU 10DH ;定义读/写地址寄存器地址RD EQU 0 ;定义读启动控制位位地址WR EQU 1 ;定义写启动控制位位地址WREN EQU 2 ;定义写使能控制位位地址EEPGD EQU 7 ;定义访问目标选择控制位位址F EQU 1 ;定义目标寄存器为RAM的指示符W EQU 0 ;定义目标寄存器为W的指示符ADDR EQU 70H ;定义地址变量DATA1 EQU 71H ;定义数据变量;*************************************ORG 0000H ;NOP ;放置一条ICD必须的空操作指令GOTO MAIN ;ORG 0008H ;MAINBCF STATUS,RP1 ;选体1为当前体BSF STATUS,RP0 ;MOVLW 00H ;设定RC全部为输出MOVWF TRISC ;BSF STATUS,RP1 ;体3为当前体CLRF ADDR ;地址变量清0CLRF DATA1 ;数据变量清0WRITEBSF STATUS,RP1 ;选定体3BTFSC EECON1,WR ;上一次写操作是否完成GOTO $-1 ;否!返回继续检测BCF STATUS,RP0 ;选定体2MOVF ADDR,W ;取地址MOVWF EEADR ;送地址寄存器MOVF DATA1,W ;取数据MOVWF EEDATA ;送数据寄存器BSF STATUS,RP0 ;选定体3BCF EECON1,EEPGD ;选定EEPROM为访问对向BSF EECON1,WREN ;开放写操作使能控制MOVLW 55H ;MOVWF EECON2 ;送55H到寄存器EECON2(读写内部EEPROM,这句是固定的) MOVLW 0AAH ;MOVWF EECON2 ;送AAH到寄存器EECON2(读写内部EEPROM,这句是固定的) BSF EECON1,WR ;启动写操作BCF EECON1,WREN ;禁止写操作发生INCF DATA1,F ;数据递增INCF ADDR,F ;地址递增MOVF ADDR,W ;XORLW D'64' ;将当前地址与64比较BTFSS STATUS,Z ;检测=64否GOTO WRITE ;否!继续写后面单元READ1DECF ADDR,F ;地址递减BCF STATUS,RP0 ;选体2为当前体BSF STATUS,RP1 ;MOVF ADDR,W ;取地址MOVWF EEADR ;送地址寄存器BSF STATUS,RP0 ;选体3为当前体BCF EECON1,EEPGD ;选定EEPROM为访问对象BSF EECON1,RD ;启动读操作BCF STATUS,RP0 ;体2为当前体MOVF EEDATA,W ;取数据BCF STATUS,RP1 ;体0为当前体MOVWF PORTC ;送显LEDCALL DELAY ;调用廷时子程序MOVF ADDR,F ;检测当前地址BTFSS STATUS,Z ;是否为0?是!跳一步GOTO READ1 ;否!返回继续读出和显示READ2INCF ADDR,F ;地址递增BCF STATUS,RP0 ;选体2为当前体BSF STATUS,RP1 ;MOVF ADDR,W ;取地址MOVWF EEADR ;送地址寄存器BSF STATUS,RP0 ;选体3为当前体BCF EECON1,EEPGD ;选定EEPROM为访问对象BSF EECON1,RD ;启动读操作BCF STATUS,RP0 ;体2为当前体MOVF EEDATA,W ;取数据BCF STATUS,RP1 ;体0为当前体CALL LED_SHOW ;送数码管显示CALL DELAY ;调用廷时子程序MOVF ADDR,W ;检测当前地址与64比较XORLW D'64' ;BTFSS STATUS,Z ;是否等于64GOTO READ2 ;否!返回继续读出和显示GOTO READ1 ;返回大循环起点;******************************************DELAYMOVLW 0 ;MOVWF 72H ;将外层循环参数值256送外层循环寄存器DELAY1MOVLW 0 ;将内层循环参数值256送内层循环寄存器MOVWF 73H ;DECFSZ 73H,1 ;递减廷时程序GOTO $-1 ;DECFSZ 72H,1 ;GOTO DELAY1 ;RETURN;==========================================================; 2位LED共阳数码管显示模块; 入口: 待显示的数据在W中;----------------------------------------------------------LCD1 EQU 20H ;定义显示缓存单元LCD2 EQU 21HW_TEMP EQU 22H ;保护单元STATUS_TEMP EQU 23HCOUNT0 EQU 24HCOUNT1 EQU 25HCOUNT2 EQU 26HLED_SHOW; MOVLW 7FH ;;;;;;;MOVWF LCD1 ;现场保护,将W的内容暂存于LCD1MOVWF W_TEMP ;现场保护[W-->W_TEMP]SWAPF STATUS,W ;用SWAPF才不会影响标志位[W与STATUS高低4位交换] MOVWF STATUS_TEMP ;将W和STATUS存入各保护寄存器[STATUS-->STATUS_TEMP]BCF STATUS,RP1 ;选体1为当前体BSF STATUS,RP0 ;MOVLW 00HMOVWF TRISD ;设RD为输出口BCF STATUS,RP0 ;恢复体0; MOVWF LCD1 ;W-->LCD1MOVF LCD1,W ;LCD1-->WANDLW B'11110000' ;0FH与W相"与"后送WMOVWF LCD2 ;W-->FSWAPF LCD2 ;F高低4位互换MOVF LCD2,WCALL CONVERT ;绎码MOVWF PORTCMOVLW 02HMOVWF PORTD ;开LCD十位CALL DELAY2 ;延时MOVLW 0HMOVWF PORTD ;关LCD个位MOVF LCD1,W ;F-->WANDLW B'00001111' ;0FH与W相"与"后送WCALL CONVERT ;绎码MOVWF PORTCMOVLW 01HMOVWF PORTD ;开LCD个位CALL DELAY2 ;延时MOVLW 0HMOVWF PORTD ;关LCD个位SWAPF STATUS_TEMP,W ;恢复中断前STATUS,W的值MOVWF STATUSSWAPF W_TEMP,F ;W_TEMP高低4位互换SWAPF W_TEMP,W ;(用SWAPF才不会影响STATUS的值)RETURN ;子程序返回;==========================================================;-------------------- 共阳顺序7段数码管段码 --------------- CONVERT ;取数码管段码ADDWF PCL,1 ;地址偏移量加当前PC值TABLE RETLW 0C0H ;0RETLW 0F9H ;1 RETLW 0A4H ;2RETLW 0B0H ;3RETLW 99H ;4RETLW 92H ;5RETLW 82H ;6RETLW 0F8H ;7RETLW 80H ;8RETLW 90H ;9RETLW 88H ;ARETLW 83H ;bRETLW 0C6H ;cRETLW 0A1H ;dRETLW 86H ;ERETLW 8EH ;F; RETLW 7FH ;. 小数点RETLW 00H ;结束符;---------------------------------------------------------- ;--------------------------- 廷时子程序 ----------------- DELAY2MOVLW .2 ;设置延时常数 [.2--即为2] MOVWF COUNT0L1MOVLW .50 ;MOVWF COUNT1L2MOVLW .100 ;MOVWF COUNT2L3DECFSZ COUNT2,1 ;递减循环GOTO L3 ;DECFSZ COUNT1,1 ;GOTO L2 ;DECFSZ COUNT0,1 ;GOTO L1 ;RETLW 0;========================================================== END。
PIC单片机的EEPROM读写实例及说明
PIC单片机的EEPROM读写实例及说明; PIC 单片机的EEPROM 读写实例及说明;****************************************************************************; This is a program to test the function of readingwritting for EEPROM.; You can observe the value of register(30H--?) buy changing “VALU” and “WRC_”.; Notice that:it must be { ADDR+WRC_=0ffh } !;****************************************************************************include “p16f877.inc”ADDR EQU 20H ;写入地址寄存器VALU EQU21H ;写入值REC_ EQU 22H ;读计数WRC_ EQU 24H ;写计数org 0goto mainmainbcf STATUS,RP1bcf STATUS,RP0 ;bank0movlw 10hmovwf ADDR ;写入EEPROM 初始值movlw 90hmovwf VALU ;初始写入值movlw 30hmovwf FSR ;间址,读出值初始存放地址movlw 0Fhmovwf WRC_ ;写入次数movwf REC_;incf REC_ ;读出次数wri_ ;写子程序bsf STATUS,RP1bsf STATUS,RP0 ;bank3btfsc EECON1,WRgoto $-1bcf STATUS,RP0bcf STATUS,RP1 ;bank0movf ADDR,Wbsf STATUS,RP1 ;bank2movwf EEADRbcf STATUS,RP1 ;bank0movf VALU,Wbsf STATUS,RP1 ;bank2movwf EEDATAbsf STATUS,RP0 ;bank3bcf EECON1,EEPGD ;to data memorybsf EECON1,WRENbcf INTCON,GIEmovlw 55hmovwf EECON2movlw 0aahmovwf EECON2bsf EECON1,WRbcf STATUS,RP0bcf STATUS,RP1 ;bank0incf ADDR,1decf VALU,1decfsz WRC_ ;all write,to read_goto wri_read_ ;读子程序bcf STATUS,RP1bcf STATUS,RP0 ;bank0decf ADDR ;next valuebsf STATUS,RP1 ;bank2movwf EEADRbsf STATUS,RP0 ;bank3EEwr.asm 程序说明:1、本程序是对PIC16F877 单片机的EEPROM 数据区进行读写的演示程序;。
PIC16f877中文资料
PIC16f877中文资料PIC16F877原理简介1.1 PIC16F877特性:PIC16F877是由Microchip公司所生产开发的新产品,属于PICmicro系列单片微机,具有Flash program程序内存功能,可以重复烧录程序,适合教学、开发新产品等用途;而其内建ICD(In Circuit Debug)功能,可以让使用者直接在单片机电路或产品上,进行如暂停微处理器执行、观看缓存器内容等,让使用者能快速地进行程序除错与开发。
如图1为PIC16F877的40根接脚图,PDIP是指一般最常见的DIP(Dual In Line Package)包装,而PIC单片机也有PLCC(Plastic Leaded Chip Carrier)与QFP(Quad Flat Package)两种形式的包装,依照不同的需求,寻找不同的包装形式。
如图所示,每根接脚都有其特定功能,例如Pin11与Pin32(VDD)为正电源接脚,Pin12与Pin31(VSS)为地线接脚;而有些接脚有两种甚至三种以上功能,例如Pin2(RA0/AN0)代表PORTA的第一支接脚,在系统重置(Reset)后,可自动成为模拟输入接脚,接收模拟讯号,也可经由程序规划为数字输出输入接脚。
图1. PDIP40引脚PIC16F877接脚说明图2. PDIP28和SOIC28引脚PIC16F877接脚图说明图3. PLCC44引脚PIC16F877脚位图说明图4. QFP44引脚PIC16F877引脚图说明PIC16F877属于闪控式(Flash)单片机,可以重复烧录,其ROM 的容量总共是8K words,以2K为一个page,区分为4个pages;内部RAM总共有512个字节(00f~1FFh),以128个字节为一个Bank,共区分为4个Bank,如图5所示,每个Bank的前半段都有其特殊用途,分别连接到其特殊功能模块,例如I/O、CCP、Timer、USART、MSSP等。
PIC单片机的C语言编程
PIC单片机的C语言编程简介PIC(Peripheral Interface Controller)是一种广泛使用的单片机系列,由美国微芯科技公司(Microchip Technology Inc.)开发和生产。
其特点是体积小、功耗低、功能强大,并且具有高性价比,因此在嵌入式系统领域得到了广泛的应用。
在PIC单片机的编程中,C语言是最常用的编程语言之一。
本文将介绍如何在PIC单片机上使用C语言进行编程。
准备工作在开始C语言编程之前,我们需要准备以下工具和设备:1.PIC单片机开发板:选择一款适合你的需求的PIC单片机开发板,例如PIC16F877A。
2.编程软件:Microchip公司的MPLAB IDE是最常用的PIC单片机编程软件之一,可以在官方网站上免费下载安装。
3.编程语言:C语言是PIC单片机常用的编程语言,具有丰富的库函数和易于学习的语法。
第一个C程序编写第一个C程序是入门PIC单片机编程的第一步。
以下是一个简单的LED闪烁程序示例:#include <xc.h>// 包含使用于PIC单片机的头文件#define _XTAL_FREQ 4000000 // 定义晶振频率为4MHz// 主函数void main(void){TRISB = 0b00000000; // 将PORTB所有引脚设为输出PORTB = 0b00000001; // 将RB0引脚输出高电平while(1){PORTBbits.RB0 = 1; // RB0引脚输出高电平__delay_ms(1000); // 延时1秒PORTBbits.RB0 = 0; // RB0引脚输出低电平__delay_ms(1000); // 延时1秒}}在这个程序中,我们使用了xc.h头文件来包含适用于PIC单片机的库函数和宏定义。
使用#define指令定义了晶振频率为4MHz,可以根据自己的实际情况进行修改。
在main函数中,通过TRISB寄存器将PORTB所有引脚设置为输出模式,并使用PORTB寄存器将RB0引脚输出高电平。
PIC单片机EEPROM的读写程序
。TEEHSATAD 考参 �似类 MORPEE 写读与程过体具写读的 HSALF �3 。)个这考参要前序程编(TEEHSATAD 见可序程编汇体具 。零清被否是 RW�置设被否是 FIEE 查检须必件软则�成完有没 1 骤步果如。 �零清件软由须 必 FIEE�置设被 FIEE 而零清被位 RW�时束结期周写在 �01 。NERW 除清 。 �断中到用要需果如�断中放开 。位 RW 置设 �3� 。 �2NOCEE 入写后 然�W 入写先首�步两含包� 。2NOCEE 入写 AAX0 将 �2� 。 �2NOCEE 入写后 然�W 入写先首�步两含包� 。2NOCEE 入写 55X0 将 �1� �序顺的骤步个 5 面下行执格严 。断中 elbasiD 。NERW 置设 。位 DGPEE 清 .ATADEE 入写据数位 8 将 。制限的件硬于大会不度长址地保确�RDAEE 入写址地将 �7 �6 �5 �4 �3 �2 CIP
。程 过写于处正是不是看位 RW 查检�成完有没 01 骤步果如 �1
�骤步的 MORPEE 写 。行进在正作操写有没证保要前程过作操写个 一始开在。零清 NERW 对须必件软后完写。RW 置设能才后置设被 NERW 在有只 。零持保须必间时它其 �据数写在正了除位 NERW 据数 MORPEE 写 。TEEHSATAD 见可序程编汇体具 。数读 ATADEE 从 。位 DR 置设 。位 DGPEE 除清 。制限的件硬于大会不度长址地保确 �ATADEE 入写址地将 �4 �3 �2 �1 �3
的中 ATADEE:HTADEE 而�除擦被会将据数的中 RDAEE:HRDAEE 。 令 指 行 执 止 停 会 将 机 片 单 � 置 设 被 R W 和 N E RW 旦 一 �HSALF 于对 。1 置被 FIEE �零清被会将址地的 RDAEE 后然 �入写据 数的中 ATADEE 将会就 RW 和 NERW 了置设旦一�据数 MORPEE 于 对 。 零 清 位 识 标 该 对 先 首 须 必 前 之 RW 置 设 在 � 置 设 被 后 束 结 程过写当 FIEE 志标断中。零清动自被会后束结作操写�位始初作操 写是位 RW。作操写行进以可则 1=�位能使作操写是 NERW。FIEE 和 RRERW 位志标个两�NERW 和 RW 位制控个两有作操写 。据数到读器 存寄 ATADEE:HTADEE 从以可令指条两后置设被在 �据数的 HSALF 于 对 而 。 据 数 到 读 器 存 寄 ATADEE 从 以 可 上 马 会 就 后 置 设 被位 该 �作操读的 MORPEE 于对。零清动自会后束结作操读。据数到读器 存寄据数从能就 1 成置设被旦一�DR 位加附个一到用要作操读 。作操行进 HSALF 对是则 1= �作操行进 MORPEE 对 �0=DGPEE 。断中外意的中程过写止防来用被是而�器存 寄的上义意正真个一是不 2NOCEE�化始初置配来用 1NOCEE 器存寄 2NOCEE 和 1NOCEE �1 。写读的节字/字行进�行执常正的序程响影 会不 MORPEE 。 �列系 X78F61�据数位 41 储存 ATADEE:HTADEE � 址 地 位 31 存 保 RDAEE:HRDAEE � 断 中 和 令 指 条 一 下 行 执会才束结作操写到直�行运的令指停暂会作操写的 HSALF 对
pic16单片机读写
pic16单片机读写Eeprom读写函数用于pic16 系列单片机void write_eeprom(unsigned char addr,unsigned char data) {do{;}while(WR==1); //上一次写操作是否完成EEADR=addr; //EEPROM地址EEDATA=data; //准备写入EEPROM的数据EEPGD=0; //指向EEPROM数据储存器WREN=1; //使能写操作EECON2=0x55; //设置通用参数EECON2=0xAA; //设置通用参数WR=1; //开始写do{;}while(WR==1); //等待写操作完成WREN=0; //禁止写操作}unsigned char read_eeprom(unsigned char addr){unsigned char num;do{;}while(RD==1); //上一次读操作是否完成EEADR=addr; //EEPROM地址为00HEEPGD=0; //指向EEPROM数据储存器RD=1; //开始读do{;}while(RD==1); //等待读操作完成num=EEDATA; //读出return(num); //返回读出的数}下面为pic18系列的eeprom读写程序void write_eeprom(unsigned char addr,unsigned char edata) {do{;}while(WR==1); //上一次写操作是否完成NVMADR=addr; //EEPROM地址NVMADRH:NVMADRLNVMDAT=edata; //准备写入EEPROM的数据NVMDA TNVMREG1 =0; //指向EEPROM数据储存器NVMREG0 NVMREG1 :1;NVMREG0 =0;WREN=1; //使能写操作NVMCON2=0x55; //设置通用参数NVMCON2=0xAA; //设置通用参数WR=1; //开始写do{;}while(WR==1); //等待写操作完成WREN=0; //禁止写操作}unsigned char read_eeprom(unsigned char addr){unsigned char num;do{;}while(RD==1); //上一次读操作是否完成NVMADR=addr; //EEPROM地址为00HNVMREG1 =0; //指向EEPROM数据储存器NVMREG0 NVMREG1 :1;NVMREG0 =0; //指向EEPROM数据储存器RD=1; //开始读do{;}while(RD==1); //等待读操作完成num=NVMDA T; //读出return(num); //返回读出的数}。
PIC单片机16F877_SPI参考
作都无效,会将冲突检测位 WCOL (SSPCON<7>)置 1。此时用户必须用软件将 WCOL 位清 零,否则无法判别下一次对 SSPBUF 的写操作是否成功。当应用软件要接收一个有效数据时,应 该在下一个要传送的数据写入 SSPBUF 之前,将 SSPBUF 中的前一个数据读出。缓冲器满标志 位 BF (SSPSTAT<0>) 用于表示何时把接收到的数据送入 SSPBUF 寄存器 (传输完成)。当 SSPBUF 中的数据被读出后,BF 位即被清零。如果 SPI 仅仅作为一个发送器,则不必理会接收的
第 15 章 SSP
寄存器 15-2: SSPCON:同步串行口控制寄存器 (续)
bit 3:0
SSPM3:SSPM0: 同步串行口模式选择位
0000 = SPI 主控模式 , 时钟 = FOSC/4 0001 = SPI 主控模式 , 时钟 = FOSC/16 0010 = SPI 主控模式 , 时钟 = FOSC/64 0011 = SPI 主控模式 , 时钟 = TMR2 输出 /2 0100 = SPI 从动模式 , 时钟 = SCK 引脚,使能 SS 引脚控制 0101 = SPI 从动模式 , 时钟 = SCK 引脚,禁止 SS 引脚控制,SS 可用作 I/O 引脚 0110 = I2C 7 位地址的从动模式 0111 = I2C 10 位地址的从动模式 1000 = 保留 1001 = 保留 1010 = 保留 1011 = I2C 固件控制的主控模式 (从动模式空闲) 1100 = 保留 1101 = 保留 1110 = I2C 从动模式
如何利用PIC16F877A单片机读写AT24C系列储存器
如何利用PIC16F877A单片机读写AT24C系列储存器
AT24C系列在增强型PIC实验板上编程的硬件原理图如下图所示,U7为实验板上24C02芯片,SDA与单片机的RB5口相连,SCL与单片机RB4相连,七段数码管D5、D7、D8组成了显示单元,字形码的数据通过RC口送入,各数码管的显示片选信号分别不同的RA口进行控制。
在MPLab IDE软件中新建工程,加入源程序代码,同时进行芯片型号的选择和配置位的设置,我们实验所用的芯片型号为PIC16F877A。
编写的程序代码如下,其中程序流程图如下图所示。
软件代码
编好程序后将编译好的HEX码通过ICD2仿真烧写器烧入单片机芯片,上电运行,主程序中在O×01地址写入了“O×55”,在O×02地址写入了“O×aa”,然后在while循环中读出O×02地址的值,也就是我们之前写入的“O×55”,读出后显示在数码管上,我们可以看到数码管显示“170”,即“O×aa”相应的十进制数。
PIC16F877A-SPI-TC77(温度传感器)
PIC16F877A-SPI-TC77(温度传感器)---------------------------------借鉴,TCK(0-1024℃)分辨率:0.25℃TC77:分辨率0.0625℃#include#define CS RC2void initPORT();void initMSSP();void delay(unsigned char time);void display(float data);float ReadTC77();const unsigned chardisp[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void main(){float temp;initPORT();initMSSP();while(1){temp=ReadTC77();display(temp);}}/*初始化PIC 单片机端口*/void initPORT(){TRISB=0x00; //控制段选PORTB=0x00;TRISC=0xf0; //与温度传感器连接PORTC=0x00;TRISA=0x00; //控制位选PORTA=0xff;}/*初始化MSSP 模块的SPI 模式*/void initMSSP() {SSPSTAT=0x00;SSPCON=0x30;SSPIF=0;}/*读取温度传感器的13 位数值并且转换成浮点类型*/float ReadTC77(){float result,PowerTwo=1;unsigned char count,HighByte,LowByte;CS=0;SSPBUF=0;while(!SSPIF){}HighByte=SSPBUF; //获取温度寄存器的高字节SSPIF=0;SSPBUF=0;while(!SSPIF){}LowByte=SSPBUF; //获取温度寄存器的低字节SSPIF=0;CS=1;for(count=0;count>count))result+=PowerTwo;PowerTwo=PowerTwo/2.; //注意,不能换成.2,否则会出错} return result; //返回转换浮点结果}/*液晶显示*/void display(float data){unsignedintconver,First,Second,Third,Fourth;conver=data*100;First=conver/1000;Second=conv er/100%10;Third=conver/10%10;Fourth=conver%10;PORTA=0xfe; //显示十位PORTB=disp[First];delay(2);PORTB=0x00;PORTA=0xfd; //显示个位。
PIC单片机C语言编程实例
/*等待中断*/
1.1.2 程序清单
下面给出一个调试通过的例程,可作为读者的参考。调试该程序把模板 J7 上的短路跳 针拔下,以免产生冲突。
#include <pic1687x.h>
volatile unsigned char data;
TRISC=0x00;
/*SDO 引脚为输出,SCK 引脚为输出*/
}
1.2.3 程序清单
下面给出已经在实验板上调试通过的一个程序,可作为用户编制其它程序的参考。
#include
<pic1687x.h>
/*该程序用于在 8 个 LED 上依次显示 1~8 等 8 个字符*/
static volatile int table[20]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,
I;
unsigned char j;
const char table[20]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0XD8,0x80,0x90,
0x88,0x83,0xc6,0xa1,0x86,0x8e,0x7f,0xbf,0x89,0xff};
/*B 口“电平变化中断”初始化子程序*/
/*启动发送*/
do
{
;
}while(SSPIF==0);
/*等待发送完毕*/
SSPIF=0;
/*清除 SSPIF 标志*/
}
/*主程序*/
main()
{
unsigned I;
initial();
PIC单片机片内EEPROM的读写程序
PIC单片机片内EEPROM的读写程序因为也是摸索着学习PIC单片机,当要用到EEPROM存储部分系统参数,看单片机手册上的资料,觉得还是比较麻烦,然后还是不太会,然后就想找找看网上有没有现成的PIC单片机的片内EEPROM的读写程序,然后都没有找到想要的,而且对汇编语言的也不知道,所以搜索了下最后终于发现PICC编译器里面其实对内部的EEPROM的读写有头文件,可以直接来用,方法如下:PICC的安装目录下C:\Program Files\HI-TECH Software\PICC\9.81\include(这是我的电脑里目录)里面有一个eeprom_routines.h的文件这个就是关于EEPROM 中的读写程序,具体程序如下:// This header file should not be included directly// Inclusion of this file is provided indirectly by including htc.h/******************************************************************** ***//****** EEPROM memory read/write macros and function definitions *******//******************************************************************** ***//* NOTE WELL:The macro EEPROM_READ() is NOT safe to use immediately after anywrite to EEPROM, as it does NOT wait for WR to clear. This is bydesign, to allow minimal code size if a sequence of reads isdesired. To guarantee uncorrupted writes, use the functioneeprom_read() or insertwhile(WR)continue;before calling EEPROM_READ().*/#if EEPROM_SIZE > 0#ifdef __FLASHTYPE// macro versions of EEPROM write and read#define EEPROM_WRITE(addr, value) \do{ \while(WR)continue;EEADRL=(addr);EEDATA=(value); \EECON1&=0x3F;CARRY=0;if(GIE)CARRY=1;GIE=0; \WREN=1;EECON2=0x55;EECON2=0xAA;WR=1;WREN=0; \if(CARRY)GIE=1; \}while(0)#define EEPROM_READ(addr)((EEADRL=(addr)),(EECON1&=0x3F),(RD=1),EEDATA)#else // else doesn't write flash#define EEPROM_WRITE(addr, value) \do{ \while(WR)continue;EEADRL=(addr);EEDATA=(value); \CARRY=0;if(GIE)CARRY=1;GIE=0; \WREN=1;EECON2=0x55;EECON2=0xAA;WR=1;WREN=0; \if(CARRY)GIE=1; \}while(0)#define EEPROM_READ(addr) ((EEADRL=(addr)),(RD=1),EEDATA) #endif/* library function versions */extern void eeprom_write(unsigned char addr, unsigned char value); extern unsigned char eeprom_read(unsigned char addr);#endif // end EEPROM routines看到这里就知道了。
用PIC单片机实现的IC卡读写器
用PIC单片机实现的IC卡读写器摘要:详细介绍PIC单片机使用SPI方式与IC卡进行数据传输的原理和电路设计,以及使用USART方式与PC机进行串行异步通信的工作原理;介绍PIC单片机听SPI方式和USART方式的设置方法。
关键词:PIC单片机IC卡读写器SPI方式USART方式引言本设计的主要目的是介绍IC卡的数据存储技术和IC卡的数据通信,因而使用存储器卡。
由于本设计中既可与IC卡进行串行同步通信,又要与上位机进行中行异步通信,因而需要选择一种同时具有这两种通信方式的单片机。
因为PIC16F877不仅具有本设计所需要的两种通信方式,而且还具有运行速度快、低功耗、价格低等优点,所以选择PIC16F877单片机作为本设计的单片机。
图1是本设计的电路图,图中电源变换电路和发光二极管等指示电路没有画出。
图中的二极管电路是单片机与IC卡通信数据线的保护电路。
当数据线上的电压为负电压时,与地相连的二极管导通;当数据线上的电压大于+5V时,与+5V相连的二极管导通,从而保证数据线上的电压在0V~+5V之间,保护单片机和IC卡不受损坏。
图中单片机的15脚和23脚分别与IC卡的输出引脚3和4相连。
由于IC卡的输出电压为CMOS电平,而单片机能够正确的识别IC卡的输出信号,需要加上拉电阻。
1SPI工作方式串行外围设备接口SPI(SerialPeripheralInterface)总线技术是Motrola 公司推出的一种同步串行接口。
SPI总线是一种三线同步总线,因其硬件能力很强,与SPI有关的软件就相当简单,使CPU有更多的时间处理其它事务,因此得到广泛应用。
SPI模式允许8位数据同步发送和接收,支持SPI的所有四种方式。
SPI模式传输数据需要四根信号线:串行数据输出(SDO)线、串行数据输入(SDI)线、串行时钟(SCK)和从选择(SS)。
其中,从选择线只用于从属模式。
1.1SPI主模式由于控制时钟SCK的输出,主模式可以在任何时候开始传输数据。
基于PIC16F887单片机的数字钟完整c程序代码
#include <pic.h>__CONFIG (0x20F1);__CONFIG (0x3FFF); //调试用#define LCD_E RD6 //LCD E 读写使能控制#define LCD_RW RD5 //LCD 读(1)/写(0)控制线#define LCD_RS RD4 //LCD 寄存器选择数据(1)指令(0)//RD4-RD7分别接DB4-DB7,RD7为忙标志#define COM 0 //在LCD_WRITE()中的第2参数为0表示写命令#define DAT 1 //在LCD_WRITE()中的第2参数为1表示写数据#define mod RB3//模式选择(时间、闹钟、温度、秒表)#define set RB0//选择按键#define add RB1//加按键#define miu RB2//减按键#define RTR 0b00000000 //TC74的读温度命令#define TC74_ADD 0b1001101 //TC74的7位地址#define LINE1 0b10000000#define LINE2 0b11000000signed char hourt,mint,sect;//闹钟设置位int f;//闹钟显示清零判断char flag=0;//按键标志位char WW,QW,BW,SW,GW,M;char table[]="Mon Tue Wed Thu Fri Sat Sun ";//星期signed char year,month,day,week,hour,min,sec,a,T;bank1 char DD[16]; //一行LCD显示数据暂存char A[7];//DS1307读数//====LCD程序void CSH(void); //初始化void LCD_CSH(void); //LCD初始化void LCD_BUSY(void); //检测LCD是否忙char LCD_READ(void); //读LCD,忙检测用void LCD_WRITE(char,char); //LCD写1字节,命令或数据void LCD_WRITE_4(char,char); //LCD写半字节void DISP_C(char); //在指定行中显示字符,字符在数组DD中void DISP_MENU(const char *); //由常数数组显示整屏字符void DELAY_US(char);void DELAY(unsigned int);void delaynms(unsigned int);//===DS1307void IIC_SEND(char);void IIC_CSH(void);void READ_DS1307(char addr,char n);void write_DS1307(char addr,char data);void DS1307_CSH(void);//DS1307初始化void MENU_DS1307(void);//==温度void DISP_T(signed char R1); //温度在R1 signed char READ_T(void); void clock();//闹钟void set_time(void);//按键void bcd_dec(char adr,char R);char dec_bcd(char dec);void BCD(unsigned int R1);void guangbiao(void);//光标//========主程序void main(){CSH();READ_DS1307(0,7);//读DS1307 if(A[0]&0x80)DS1307_CSH();//判断是否初始化while(1){clock();set_time();//按键检测delaynms(50);if(flag==0){ READ_DS1307(0,7);//读DS1307 MENU_DS1307();//显示DS1307T=READ_T();//读温度DISP_T(T);//显示温度}}}//========初始化端口void CSH(void){TRISD=0b00000000; //控制LCD1604,全为输出RD7=1; //背光TRISB=0x0FF;RBPU=0;WPUB=0x0FF;ANSELH=0;PORTB=0x00;//===PWM设置TRISC1=0; //RC1为输出RC1=0;PR2=124; //周期为1msCCPR2L=0x32;CCP2CON=0b00000000;//关闭PWMT2CON=0b00000110; //TMR2预分频1:16,开始工IIC_CSH();LCD_CSH();}//LCD模块初始化void LCD_CSH(void){ DELAY(20); //延时20msLCD_WRITE_4(0b0011,COM); //发送控制序列DELAY_US(10); //延时100usLCD_WRITE_4(0b0011,COM); //发送控制序列DELAY_US(10); //延时100usLCD_WRITE_4(0b0011,COM); //发送控制序列DELAY_US(10); //延时100usLCD_WRITE_4(0b0010,COM); //4位数据格式LCD_BUSY(); //LCD忙检测LCD_WRITE(0b00101000,COM); //4位数据格式,2行,5×7点阵LCD_WRITE(0b00001100,COM); //D(d2)=1:打开显示,C(d1)=1:光标打开,B(d0)=1:光标不闪烁LCD_WRITE(0b00000001,COM); //清除显示DELAY(2); //延时2msLCD_WRITE(0b00000110,COM); //输入模式,I/D(d1)=1:地址加1,S(d0)=1:显示移位关闭}//========读LCD状态char LCD_READ(void){ unsigned char R1;TRISD|=0X0F; //LCD数据线为输入LCD_RS=0; //寄存器选择LCD_RW=1;NOP(); //读为1LCD_E=1;NOP(); //使能R1=0; //短延时R1=(PORTD<<4 )& 0xF0; //读数据的高4位给R1高四位LCD_E=0;NOP(); //读数据结束LCD_E=1;NOP(); //使能R1 |= (PORTD & 0x0F); //读PORTD的低4位,R1的高4位不变! LCD_E=0;NOP(); //读数据结束LCD_RW=0;return (R1);}//写一字节数R1,FLAG为写命令或数据选择,0为写命令,1为写数据//写之前先检查是否忙,写完后延时100us,分二次写4位数据/命令void LCD_WRITE(char R1,char FLAG){ char R2;TRISD&=0XF0;LCD_BUSY();R2=R1 & 0xF0; //低4位清0R2=R2>>4; //取高4位LCD_WRITE_4(R2,FLAG); //先写高4位R2=(R1 & 0x0F); //高4位清0,取低4位LCD_WRITE_4(R2,FLAG); //再送低4位DELAY_US(10); //延时100us}//写R1的低4位,FLAG为寄存器选择,1为命令,0为数据void LCD_WRITE_4(char R1,char FLAG){ TRISD&=0XF0;LCD_RW=0;NOP(); //写模式LCD_RS=FLAG;NOP(); //寄存器选择PORTD &= 0xF0;NOP(); //RD低4位先清0LCD_E=1;NOP(); //使能R1=(R1&0x0F); //R1低4位送至低4位PORTD |=R1;NOP(); //送4位LCD_E=0;NOP(); //数据送入有效,下降沿送入LCD_RS=0;NOP();PORTD &= 0xF0; //RD低4位清0}//========检测LCD是否忙void LCD_BUSY(void){ unsigned char R1;while(1){ R1=LCD_READ(); //读寄存器if ((R1 & 0x80)==0x00) //最高位为忙标志位break; };}//======延时(n)msvoid DELAY(unsigned int n){unsigned int j;char k;for (j=0;j<n;j++)for (k=246;k>0;k--) NOP();}//======延时(n)msvoid delaynms(unsigned int n){unsigned int j;char k;for (j=0;j<n;j++)for (k=246;k>0;k--) NOP();}//======延时(n×10)usvoid DELAY_US(char n){ char j;for (j=0;j<n;j++){NOP();NOP();}}//=======DS1307有关子程序//===DS1307初始化void DS1307_CSH(){write_DS1307(0x00,0X00);//秒钟设置write_DS1307(0x01,0x01);//分钟设置write_DS1307(0x02,0x01);//小时设置write_DS1307(0x03,0X01);//星期天设置write_DS1307(0x04,0x01);//日月设置write_DS1307(0x05,0x05);//月设置write_DS1307(0x06,0x12);//年设置write_DS1307(0x07,0x70);//7脚方波允许,输出1HZ}//==IIC初始化void IIC_CSH(){ TRISC =0b00011000; //SDA,SCL设置为输入SSPCON=0b00101000; //同步串口使能(SSPEN),主控方式SMP=0; //使能高速模式(400 kHz) 的压摆率控制SSPADD=4; //主控模式为波特率值,每位时间T=(SSPADD+1)/Tcy=5us } //发送数R并等待发送完成,收到从机的应答信号void IIC_SEND(char R){ SSPBUF=R; //发送while (RW==1); //在主动模式下,判断发送是否完成while (SSPIF==0); //等待发送完成while (ACKSTA T==1); //等待从机发送应答信号NOP();}//====读写DS1307程序void write_DS1307(char addr,char data){SEN=1; //发送起始位while(SEN==1); //检测起始位完成IIC_SEND(0b11010000); //送DS1307的七位地址和写功能IIC_SEND(addr); //发送要写入的地址IIC_SEND(data); //发送要写入的数PEN=1; //发送停止位while (PEN==1); //检查停止位结束}//===读DS1307void READ_DS1307(char addr,char n){char i;SEN=1; //产生起始位while (SEN==1); //检测起始位完成IIC_SEND(0b11010000); //送DS1307的7位地址IIC_SEND(addr); //此值为DS1307要读的地址PEN=1; //发送停止位while (PEN==1);//检查停止位结束NOP();RSEN=1; //发送重新启始位while(RSEN==1); //检测重新起始位完成IIC_SEND(0b11010001); //读数据for (i=0;i<n;i++) //读字节个数{ RCEN=1;while (RCEN==1);A[i]=SSPBUF; //读1字节if (i<n-1){ ACKDT=0;ACKEN=1;while (ACKEN==1);}else{ ACKDT=1;ACKEN=1;while (ACKEN==1);} //最后一字节不应答}PEN=1;while (PEN==1);}//=====显示DS1307void MENU_DS1307(void){ LCD_WRITE(0b00001100,COM); //D(d2)=1:打开显示,C(d1)=1:光标打开,B(d0)=1:光标不闪烁char i;LCD_WRITE(LINE1,COM); //DDRAM地址,第1行的第1个字符LCD_WRITE(' ',DAT);LCD_WRITE('2',DAT);LCD_WRITE('0',DAT);LCD_WRITE((A[6]>>4)+0x30,DA T);LCD_WRITE((A[6]&0x0F)+0x30,DA T);LCD_WRITE('-',DAT);LCD_WRITE((A[5]>>4)+'0',DA T);LCD_WRITE((A[5]&0x0F)+'0',DAT);LCD_WRITE('-',DAT);LCD_WRITE((A[4]>>4)+'0',DA T);LCD_WRITE((A[4]&0x0F)+'0',DAT);LCD_WRITE(' ',DAT);i=A[3]&0x07;LCD_WRITE(table[(i-1)*4],DA T);LCD_WRITE(table[(i-1)*4+1],DAT);LCD_WRITE(table[(i-1)*4+2],DAT);LCD_WRITE(table[(i-1)*4+3],DAT);//LCD_WRITE(' ',DAT);LCD_WRITE(LINE2,COM); //DDRAM地址,第2行的第1个字符LCD_WRITE(' ',DAT);LCD_WRITE((A[2]>>4)+'0',DA T);LCD_WRITE((A[2]&0x0F)+'0',DAT);LCD_WRITE(0x3A,DA T);LCD_WRITE((A[1]>>4)+'0',DA T);LCD_WRITE((A[1]&0x0F)+'0',DAT);LCD_WRITE(0x3A,DA T);LCD_WRITE((A[0]>>4)+'0',DA T);LCD_WRITE((A[0]&0x0F)+'0',DAT);LCD_WRITE(' ',DAT);}char dec_bcd(char dec){char bcd;bcd= 0;while(dec >= 10){dec -= 10;bcd++;}bcd <<= 4;bcd |= dec;return (bcd);}void bcd_dec(char adr,char R) { SW=A[adr]>>4;GW=A[adr]&0x0F;while(SW>0){R=R+10;SW--;}R+=GW;}//====按键程序void set_time(){if(mod==0){delaynms(30);if(mod==0){while(!mod);//等待M++;if(M==3){ M=0;flag=0;f=0;a=0; }}}if(M==1)//设置时间{if(set==0){delaynms(30);if(set==0){while(!set);a++;if(a==8)a=0;}}guangbiao();//光标定位,闪烁if(a==1) {if(add==0){delaynms(30);if(add==0){while(!add);bcd_dec(0,sec);sec++;if(sec==60)sec=0;write_DS1307(0,dec_bcd(sec)); }}if(miu==0){delaynms(30);if(miu==0){while(!miu);bcd_dec(0,sec);sec--;if(sec==-1)sec=59;write_DS1307(0,dec_bcd(sec)); }}}if(a==2){if(add==0){delaynms(30);if(add==0){while(!add);bcd_dec(1,min);min++;if(min==60)min=0;write_DS1307(1,dec_bcd(min)); }}if(miu==0){delaynms(30);if(miu==0){while(!miu);bcd_dec(1,min);min--;if(min==-1)min=59;write_DS1307(1,dec_bcd(min)); }}}if(a==3){if(add==0){delaynms(30);if(add==0){while(!add);bcd_dec(2,hour);hour++;if(hour==24)hour=0;write_DS1307(2,dec_bcd(hour)); }}if(miu==0){delaynms(30);if(miu==0){while(!miu);bcd_dec(2,hour);hour--;if(hour==-1)hour=23;write_DS1307(2,dec_bcd(hour)); }}}if(a==4){if(add==0){delaynms(30);if(add==0){while(!add);bcd_dec(3,week);week++;if(week==8)week=1;write_DS1307(3,dec_bcd(week)); }}if(miu==0){delaynms(30);if(miu==0){while(!miu);bcd_dec(3,week);week--;if(week==0)week=7;write_DS1307(3,dec_bcd(week)); }}}if(a==5){if(add==0){delaynms(30);if(add==0){while(!add);bcd_dec(4,day);day++;if(day==32)day=1;write_DS1307(4,dec_bcd(day));}}if(miu==0){delaynms(30);if(miu==0){while(!miu);bcd_dec(4,day); day--;if(day==0)day=31;write_DS1307(4,dec_bcd(day)); }}}if(a==6){if(add==0){delaynms(30);if(add==0){while(!add);bcd_dec(5,month);month++;if(month==13)month=1;write_DS1307(5,dec_bcd(month)); }}if(miu==0){delaynms(30);if(miu==0){while(!miu);bcd_dec(5,month);month--;if(month==0)month=12;write_DS1307(5,dec_bcd(month)); }}}if(a==7){if(add==0){delaynms(30);if(add==0){while(!add);bcd_dec(6,year);year++;if(year==99)year=0;write_DS1307(6,dec_bcd(year)); }}if(miu==0){delaynms(30);if(miu==0){while(!miu);year--;if(year==-1)year=99;bcd_dec(6,year);write_DS1307(6,dec_bcd(year)); }}}READ_DS1307(0,7);//读DS1307}//====闹钟按键设置else if(M==2){f++;flag=1;if(f==1){a=0;LCD_WRITE(LINE2+1,COM);//显示上次闹铃时间BCD(hourt); LCD_WRITE(SW+'0',DAT);LCD_WRITE(GW+'0',DAT);LCD_WRITE(LINE2+4,COM);BCD(mint);LCD_WRITE(SW+'0',DAT);LCD_WRITE(GW+'0',DAT);LCD_WRITE(LINE2+7,COM);BCD(sect);LCD_WRITE(SW+'0',DAT); LCD_WRITE(GW+'0',DAT);}if(set==0) //设置时间{delaynms(30);if(set==0){while(!set);a++;if(a==4)a=0;}}guangbiao();//光标定位,闪烁if(a==1){if(add==0){delaynms(30);if(add==0){while(!add);sect++;if(sect==60)sect=0;BCD(sect);LCD_WRITE(LINE2+7,COM);LCD_WRITE(SW+0x30,DAT); //显示十位LCD_WRITE(GW+0x30,DAT); //显示个位}}if(miu==0){delaynms(30);if(miu==0){while(!miu);sect--;if(sect==-1)sect=59;BCD(sect);LCD_WRITE(LINE2+7,COM);LCD_WRITE(SW+0x30,DAT); //显示十位LCD_WRITE(GW+0x30,DAT); //显示个位}}}if(a==2){if(add==0){delaynms(30);if(add==0){while(!add);mint++;if(mint==60)mint=0;BCD(mint);LCD_WRITE(LINE2+4,COM);LCD_WRITE(SW+0x30,DAT); //显示十位LCD_WRITE(GW+0x30,DAT); //显示个位}}if(miu==0){delaynms(30);if(miu==0){while(!miu);mint--;if(mint==-1)mint=59;BCD(mint);LCD_WRITE(LINE2+4,COM);LCD_WRITE(SW+0x30,DAT); //显示十位LCD_WRITE(GW+0x30,DAT); //显示个位}}}if(a==3){if(add==0){delaynms(30);if(add==0){while(!add);hourt++;if(hourt==24)hour=0;BCD(hourt);LCD_WRITE(LINE2+1,COM);LCD_WRITE(SW+0x30,DAT); //显示十位LCD_WRITE(GW+0x30,DAT); //显示个位}}if(miu==0){delaynms(30);if(miu==0){while(!miu);hourt--;if(hourt==-1)hourt=23;BCD(hourt);LCD_WRITE(LINE2+1,COM);LCD_WRITE(SW+0x30,DAT); //显示十位LCD_WRITE(GW+0x30,DAT); //显示个位}}}}}//====光标定位void guangbiao(void){switch(a){case(1):LCD_WRITE(0b11001000,COM);LCD_WRITE(0b00001111,COM);break;/ /定位秒,光标打开,B(d0)=1:光标闪烁case(2):LCD_WRITE(0b11000101,COM);LCD_WRITE(0b00001111,COM);break;/ /定位分,光标打开,B(d0)=1:光标闪烁case(3):LCD_WRITE(0b11000010,COM);LCD_WRITE(0b00001111,COM);break;/ /定位时,光标打开,B(d0)=1:光标闪烁case(4):LCD_WRITE(0b10001110,COM);LCD_WRITE(0b00001111,COM);break;/ /定位星期,光标打开,B(d0)=1:光标闪烁case(5):LCD_WRITE(0b10001010,COM);LCD_WRITE(0b00001111,COM);break;/ /定位日,光标打开,B(d0)=1:光标闪烁case(6):LCD_WRITE(0b10000111,COM);LCD_WRITE(0b00001111,COM);break;/ /定位月,光标打开,B(d0)=1:光标闪烁case(7):LCD_WRITE(0b10000100,COM);LCD_WRITE(0b00001111,COM);break;/ /定位秒,光标打开,B(d0)=1:光标闪烁case(8):LCD_WRITE(0b10000010,COM);LCD_WRITE(0b00001111,COM);break;/ /定位秒,光标打开,B(d0)=1:光标闪烁}}//=====读TC74的温度值signed char READ_T(void){ signed char R1;SEN=1; //开始条件while (SEN==1); //检测开始条件是否完成?IIC_SEND(TC74_ADD<<1); //送TC74地址(写)IIC_SEND(RTR); //写RTR命令(写)RSEN=1; //重新开始条件while (RSEN==1); //等待重新开始条件结束IIC_SEND((TC74_ADD<<1)+1);//发送TC74地址(读)RCEN=1; //接收使能while (RCEN==1); //等待接收完成R1=SSPBUF; //接收数据存入R1PEN=1; //停止位while(PEN==0);return(R1);}//从R1双字节数转换为十进制数万位-个位:WW,QW,BW,SW,GW void BCD(unsigned int R1){ WW=0;QW=0;BW=0;SW=0;GW=0;while(R1>=10000){R1-=10000;WW++;}while(R1>=1000){R1-=1000;QW++;}while(R1>=100){R1-=100;BW++;}while(R1>=10){R1-=10; SW++;}GW=R1;}//===温度显示void DISP_T(signed char R1) //温度在R1{ char R2;if (R1>=0)BCD(R1);else{ R2=~(R1)+1;BCD(R2);}if (R1<0){LCD_WRITE(LINE2+10,COM); //DDRAM地址,第1行的第5个字符LCD_WRITE('-',DAT);}if (R1>=0) //只在温度为正时才显示百位LCD_WRITE(BW+0x30,DAT); //显示百位,数字加上0x30即为相应的ASCII码,下同LCD_WRITE(SW+0x30,DAT); //显示十位LCD_WRITE(GW+0x30,DAT); //显示个位LCD_WRITE(0xDF,DA T); //°LCD_WRITE('C',DAT);LCD_WRITE(' ',DAT);}//====闹钟void clock(){ if(!mod||!set||!add||!miu){delaynms(30);if(!mod||!set||!add||!miu);CCP2CON=0b00000000; //关PWM模式}BCD(sect);if(SW==(A[0]>>4)&&GW==(A[0]&0x0F)) {BCD(mint);if(SW==(A[1]>>4)&&GW==(A[1]&0x0F)) {BCD(hourt);if(SW==(A[2]>>4)&&GW==(A[2]&0x0F)) CCP2CON=0b00001100; //开PWM模式}}}。
pic单片机16F877与spi接口的eeprom读写C程序
TRISC4=1;
SSPCON=0b00100000;
INTCON=0x00;
SSPSTAT=0b11000000;
ADCON1=0b00000110;
TRISA1=0;
}
//*----spi comuncation
void spi_com(unsigned char x)
{
SSPBUF=x;
TRISD=0b00110000;
unsigned char d=4,one,ten,hund,thou;
unsigned char seg8[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,
0x07,0x7F,0x67};//显示比划代码
one=x%10;
ten=x/10%10;
while(SSPIF==0);
SSPIF=0;
}
//-----------spi enable
void spi_en()
{
RA1=0;
spi_com(0x06);//WREN code
RA1=1;
nop();
}
//send data ========
void send(unsigned char data,unsigned char add)
delay(300);
//for see to delay
RD2=0;//stop display ten
delay(4);
//stop to delay
PORTB=seg8[hund];
//display hund code to PORTB
RD1=1;
//begain to display
PIC16F877ASPI通信C程序
void main(void)
{
CSH();//初始化
number=0x0D;
while(1)
{
if(b==1)//若按键,则进行读写操作
{
WRITE(number);//发送数据
//RB5=1;
DELAY(1);
ERROR=0;//错误标志位清零
PORTD=0;
SSPEN=1;//相应的引脚为一般的I/O口
CKP=1;//空闲时钟为高电平
SMP=1;//在数据信号的末端采样
CKE=1;//下降沿发送数据
SSPCON+=0b0001;//主控模式,时钟为fosc/16
}
char SPI_WRITE(char R )
{char BUF;
SSPBUF=R;//要发的数写入SSPBUF寄存器
{
for (k=1024;k>0;k--)NOP();//DELAY(30);//防抖动
INTF=0;//清标志位
b=1;
}
}
//延时(n)ms
void DELAY(unsigned int n)
{unsigned int j;
char k;
for (j=0;j<n;j++)
for (k=246;k>0;k--)NOP();
char SPI_WRITE(char R); //SPI发送函数
void WRITE(char number);//SPI写函数
void READ(void);//SPI接收函数
void interrupt ISR(void);//按键中断程序
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
0x07,0x7F,0x67};//显示比划代码
one=x%10;
ten=x/10%10;
hund=x/100%10;
thou=x/1000%10;
while(d>0)
{
PORTB=seg8[one];
//pic单片机16F877与spi接口的eeprom读写C程序
//显示采用扫描
//晶振7.3728MHz
//调试成功
//--------作者:高冀华
#include<pic.h>
#include<stdlib.h>
#define nop() asm("nop")
unsigned int word;
RD3=1;
delay(300);
RD3=0;
delay(4);
PORTB=seg8[ten];
//display ten code to PORTB
RD2=1;
//begain to display
delay(300);
//for see to delay
RD2=0;//stop display ten
{
unsigned char data2;
RA1=0;//启动
nop();
spi_com(0x03);//发读指令
spi_com(add2);
spi_com(0);//为eeprom输出data,提供时钟用*******
data2=SSPBUF;
RA1=1;// stop
return data2;
}
//------------
void main()
{
beep();
spi_res();
word=8888;
while(1)
{
if(RD5==0)
{send(rand(),12);
beep();
}
if(RD4==0)
{
word=read(12);
}
display(word);
}
}
//stop to delay
PORTB=seg8[thou];
//display thou code to PORTB
RD0=1;
//begain to display
delay(300);
//for see to delay
RD0=0;//stop display thou
delay(4);
//stop to delay
delay(4);
//stop to delay
PORTB=seg8[hund];
//display hund code to PORTB
RD1=1;
//begain to display
delay(300);
//for see to delay
RD1=0;//stop display hund
delay(4);
void spi_en()
{
RA1=0;
spi_com(0x06);//WREN code
RA1=1;
nop();
}
//send data ========
void send(unsigned char data,unsigned char add)
{
spi_en();//spi enable
RA1=0;
unsigned char temp;
void delay(unsigned int k)
{
while(k>0)
{k--;}
}
// display zone
void display(unsigned int x)
{
TRISB=0;
TRISD=0b00110000;
unsigned char d=4,one,ten,hund,thou;
d--;
//d=d-1
}
}
void beep()
{
TRISD7=0;
RD7=1;
delay(10000);
RD7=0;
}
//======spi reset====
void spi_res()
{
TRISC3=0;
TRISC5=0;
TRISC4=1;
SSPCON=0b00100000;
INTCON=0x00;
SSPSTAT=0b11000000;
ADCON1=0b00000110;
TRISA1=0;
}
//*----spi comuncation
void spi_com(unsigned char x)
{
SSPBUF=x;
while(SSPIF==0);
SSPIF=0;
}
//-----------spi enable
nop();e
spi_com(add);
spi_com(data);
RA1=1;
nop();
}
//=====read data===精华在这里,我用了几天才成,书上大部分是错的===
unsigned char read(unsigned char add2)