PIC16F877A与EEPROM进行SPI通信C程序
- 格式:doc
- 大小:27.50 KB
- 文档页数:3
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 信号,所以它可以在任何时候启。
pic16f877a编程实例pic16f877a是一款常用的单片机,被广泛应用于嵌入式系统中。
它具有多种功能和强大的性能,可以实现各种应用需求。
本文将以pic16f877a编程实例为主题,介绍其基本特性和常见应用。
pic16f877a是一款8位单片机,采用哈佛架构,具有高性能和低功耗的特点。
它内置了8KB的程序存储器,368字节的数据存储器,以及35个I/O引脚,可以满足大多数嵌入式系统的需求。
我们来看一个简单的实例,通过pic16f877a控制LED灯的开关。
```c#include <pic16f877a.h>void main() {TRISB0 = 0; // 设置RB0为输出引脚while(1) {RB0 = 1; // 将RB0引脚电平设置为高,LED灯亮__delay_ms(1000); // 延时1秒RB0 = 0; // 将RB0引脚电平设置为低,LED灯灭__delay_ms(1000); // 延时1秒}}```在上面的程序中,我们首先将RB0引脚设置为输出引脚,然后进入一个无限循环。
在循环中,我们将RB0引脚电平设置为高,LED灯亮起,然后延时1秒;然后将RB0引脚电平设置为低,LED灯熄灭,再次延时1秒。
通过不断重复这个过程,我们可以实现LED灯的闪烁效果。
除了控制LED灯,pic16f877a还可以用来控制其他外设,如蜂鸣器、液晶显示屏等。
下面是一个使用pic16f877a控制蜂鸣器的实例。
```c#include <pic16f877a.h>void main() {TRISB0 = 0; // 设置RB0为输出引脚while(1) {RB0 = 1; // 将RB0引脚电平设置为高,蜂鸣器鸣叫__delay_ms(1000); // 延时1秒RB0 = 0; // 将RB0引脚电平设置为低,蜂鸣器停止鸣叫__delay_ms(1000); // 延时1秒}}```在上面的程序中,我们同样将RB0引脚设置为输出引脚,并进入一个无限循环。
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引脚输出高电平。
PIC16F877A单片机是microchip公司的产品,它采用14位的RISC指令系统,内部集成了A/D转换器、EEPROM、模拟比较器、带比较和捕捉功能的定时器/计数器、PWM输出、异步串行通信电路等。
1.程序存储器程序存储器和堆栈PIC16F877A单片机内部具有8K×14位的Flash程序存储器,程序存储器具有13位宽度的程序计数器地址范围:0000H-1FFFH。
由程序计数器提供13条地址线进行单元选择,每个单元宽14位,即PIC16F877A的指令字节宽度为14位,能够存放一条PIC单片机系统指令。
在系统上电或其他复位情况下,程序计数器均从0000H地址单元开始工作。
如果遇到调用子程序或系统发生事件中断时,将把当前程序断点处的地址送入8级×14位的堆栈区域进行保护。
堆栈是一个独立的存储区域,在调用的子程序或中断服务程序执行完后,再恢复断点地址。
通过14位程序总线,取出对应程序之灵的机器码,送入指令存储器,将组成的操作码和操作数进行有效分离。
如果操作数为地址,则进入地址复用器;如果操作数为数据,则进入数据复用器。
而操作码将在指令译码和控制单元中转化为相应的功能操作。
PIC的多数指令均是顺序执行,即使条件跳转也是隔行间接跳转。
具有大范围转移功能的指令只有两条:无条件GOTO语句和调用子程序CALL语句。
但它们受到2KB范围的约束。
所以必须将整个程序存储器以2KB为单位进行分页。
PIC16F877A单片机的上电复位地址是0000H,中端口地址是0004H,中断产生时PC指针会自动指向该地址。
在进行中断应用时,特别是涉及多个中断同时打开时,必须要逐个对中断标志进行判断。
编程时,在0000H-0003H单元内要放置一条GOTO跳转指令,跳转到主程序,以避开0004H存储器单元。
2.数据存储器数据存储器PIC单片机的数据存储器与传统的MCS-51单片机一样,在配置结构上可分为通用寄存器和特殊功能寄存器两大类。
#include<pic.h>
__CONFIG(0x3F39);
void CSH(void); //初始化子程序
void DELAY(unsigned int n);//函数声明
char SPI_WRITE(char R); //SPI发送函数
void WRITE(char number); //SPI写函数
void READ(void); //SPI接收函数
void interrupt ISR(void);//按键中断程序
int b=0;
bit ERROR; //标志位
char B;
char number;//存放PORTD的数,全局变量
void main(void)
{
CSH(); //初始化
number=0x0D;
while(1)
{
if(b==1) //若按键,则进行读写操作
{
WRITE(number); //发送数据
// RB5=1;
DELAY(1);
ERROR=0; //错误标志位清零
READ(); //读取数据
if(B!=number) //如果接受与发送的数据不相等,则发生错误
{ERROR=1;};
DELAY(1);
// RB6=1;
if(ERROR==1) //若发生错误,灯亮
{RB4=1;}
b=0;
PORTD=number; //D口显示发送的数据
}
}
}
//初始化程序
void CSH(void)
{ OPTION_REG=0b01000000;
INTCON=0b10010000;//中断初始化关++++++++
TRISB=1; //RB0口为输入关++++++++++++
TRISC=0b00010001;//C口SDO为输出SDI为输入,SCK为输出,RC1输出RC0输入开TRISD=0; //D口全为输出
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寄存器
while(BF==0);//等待发送完毕
BUF=SSPBUF;
return(BUF);
}
void WRITE(char number)
{ char A;
RC2=0; //片选信号,低电平有效
SPI_WRITE(0b00000110); //允许写入
RC2=1; //完成写使能
RC2=0; //片选信号,低电平有效
A=SPI_WRITE(0b00000010); //写指令
A=SPI_WRITE(0b00000100); //写数据的地址
A=SPI_WRITE(number); //发送数据
RC2=1; //完成写操作
DELAY(5);
}
void interrupt ISR(void)
{ char a;int k;
if(INTF==1)
{
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();
}
void READ(void)
{
RC2=0; //片选信号,低电平有效
B=SPI_WRITE(0b00000011); //写读取数据指令B=SPI_WRITE(0b00000100); //写读取数据地址B=SPI_WRITE(0); //发空数据,为了读取数据RC2=1; //完成读写操作
DELAY(1);
}。