主机程序
#include"iostm8s103k3.h"
#include"uart1.h"
void CLK_Init(void)
{
CLK_CKDIVR_HSIDIV = 0; //1分频
}
void GPIO_Init(void)
{
/*一主一从高速模式(GPIO主模式)*/
PC_DDR=0x6f; //MISO为悬空输入,MISO为高速推挽输出,SCK高速推挽输出
PC_CR1=0x6f;
PC_CR2=0x60;
}
void SPI_Init(void)
{
CLK_PCKENR1=0xff;//接通外设时钟门控制器
SPI_CR1=0x35;
SPI_CR2=0x03;
SPI_CR1|=0x40;
/*高位先发,分频128,主机模式,空闲为低,第二时钟沿采样,双向单线模式内部使能
NSS管脚,禁止CRC*/
}
void delayus(void)
{
asm("nop"); //一个asm("nop")函数经过示波器测试代表100ns
asm("nop");
asm("nop");
asm("nop");
}
/*---- 毫秒级延时程序---------------------*/
void delayms(unsigned int time)
{
unsigned int i;
while(time--)
for(i=4;i>0;i--)
delayus();
}
void Write_Byte(uchar byte)
{
SPI_DR = byte; /* 将发送的数据写到数据寄存器 */
delayus();
delayus();
delayus();
while(!(SPI_SR & 0x02)); /* 等待发送寄存器为空 */
}
uchar Read_Write(uchar byte)
{
uchar Rvalue;
while(!(SPI_SR & 0x02)); /* 等待发送寄存器为空 */
delayus();
delayus();
SPI_DR =byte; /* 发送一个无效字节,以产生接收时钟*/
while(!(SPI_SR & 0x01)); /* 等待接受寄存器满 */
delayus();
delayus();
delayus();
Rvalue=SPI_DR;
return Rvalue;
}
int main(void)
{
int k=0;
asm("sim"); //关总中断
uart1_init();
CLK_Init();
GPIO_Init();
SPI_Init();
asm("rim"); //开总中断
//Write_Byte(1);
Read_Write(0);
while(1)
{
k=Read_Write(11);
uart1_send(k);//通过UART口检测从机发送过来的
delayms(100);
k=Read_Write(15);
uart1_send(k); //通过UART口检测从机发送过来的
delayms(100);
}
}
//#pragma vector = UART1_R_RXNE_vector
//__interrupt void uart1rxd(void)
//{
// data = UART1_DR;
//}
从机程序
#include"iostm8s103k3.h"
#include"led.h"
#include"delay.h"
uint m,flag;
void CLK_Init(void)
{
CLK_CKDIVR_HSIDIV = 0; //1分频
}
void GPIOC_Init(void)
{
/*一主一从高速模式(GPIO从模式)*/
PC_DDR=0x8f; //MISO为为高速推挽输出,MISO为悬空输入,SCK悬空输入
PC_CR1=0x8f;
PC_CR2=0x80;
}
void GPIO_Init(void)
{
PB_DDR=0xff; //MISO为悬空输入,MISO为高速推挽输出,SCK高速推挽输出
PB_CR1=0xff;
PB_CR2=0x00;
PD_DDR=0xff; //MISO为悬空输入,MISO为高速推挽输出,SCK高速推挽输出
PD_CR1=0xff;
PD_CR2=0x00;
}
void SPI_Init(void)
{
/*从模式SPI寄存器初始化*/
CLK_PCKENR1=0xff; //接通外设时钟门控制器
SPI_CR1=0x31;
SPI_CR2=0x02;
SPI_CR1|=0x40;
/* 高位先发,分频128,从机模式,空闲为低,第二时钟沿采样,双向单线模式内部使能
NSS管脚,禁止CRC*/
}
void Write_Byte(uchar byte)
{
SPI_DR = byte; /* 将发送的数据写到数据寄存器 */
while(!(SPI_SR & 0x02)); /* 等待发送寄存器为空 */
}
uchar Read_Write(uchar byte)
{
uchar Rvalue;
while(!(SPI_SR & 0x02)); /* 等待发送寄存器为空 */
delayus();
SPI_DR = byte; /* 发送一个无效字节,以产生接收时钟*/
while(!(SPI_SR & 0x01)); /* 等待接受寄存器满 */
delayus();
Rvalue=SPI_DR;
return Rvalue;
}
uchar Read_Byte()
{
uint Rvalue;
while(!(SPI_SR & 0x01)); /* 等待接受寄存器满 */
delayus();
Rvalue=SPI_DR;
return Rvalue;
}
int main(void)
{
asm("sim"); //关总中断
CLK_Init();
GPIOC_Init();
GPIO_Init();
SET_Init();
SPI_Init();
SPI_ICR=0X40;
asm("rim"); //开总中
while(1)
{
if(flag==1)
{
flag=0;
Write_Byte(m);
Display(1, m);
}
}
}
#pragma vector = 0xC
__interrupt void SPI_IRQHandler(void)
{
if((SPI_SR&0x01)==1)
{
m=Read_Byte();
flag=1;
}
//add your code hered
}
主机程序
#include"iostm8s103k3.h"
#include"uart1.h"
void CLK_Init(void)
{
CLK_CKDIVR_HSIDIV = 0; //1分频
}
void GPIO_Init(void)
{
/*一主一从高速模式(GPIO主模式)*/
PC_DDR=0x6f; //MISO为悬空输入,MISO为高速推挽输出,SCK高速推挽输出
PC_CR1=0x6f;
PC_CR2=0x60;
}
void SPI_Init(void)
{
CLK_PCKENR1=0xff;//接通外设时钟门控制器
SPI_CR1=0x35;
SPI_CR2=0x03;
SPI_CR1|=0x40;
/*高位先发,分频128,主机模式,空闲为低,第二时钟沿采样,双向单线模式内部使能
NSS管脚,禁止CRC*/
}
void delayus(void)
{
asm("nop"); //一个asm("nop")函数经过示波器测试代表100ns
asm("nop");
asm("nop");
asm("nop");
}
/*---- 毫秒级延时程序---------------------*/
void delayms(unsigned int time)
{
unsigned int i;
while(time--)
for(i=4;i>0;i--)
delayus();
}
void Write_Byte(uchar byte)
{
SPI_DR = byte; /* 将发送的数据写到数据寄存器 */
delayus();
delayus();
delayus();
while(!(SPI_SR & 0x02)); /* 等待发送寄存器为空 */
}
uchar Read_Write(uchar byte)
{
uchar Rvalue;
while(!(SPI_SR & 0x02)); /* 等待发送寄存器为空 */
delayus();
delayus();
SPI_DR =byte; /* 发送一个无效字节,以产生接收时钟*/
while(!(SPI_SR & 0x01)); /* 等待接受寄存器满 */
delayus();
delayus();
delayus();
Rvalue=SPI_DR;
return Rvalue;
}
int main(void)
{
int k=0;
asm("sim"); //关总中断
uart1_init();
CLK_Init();
GPIO_Init();
SPI_Init();
asm("rim"); //开总中断
//Write_Byte(1);
Read_Write(0);
while(1)
{
k=Read_Write(11);
uart1_send(k);//通过UART口检测从机发送过来的
delayms(100);
k=Read_Write(15);
uart1_send(k); //通过UART口检测从机发送过来的
delayms(100);
}
}
//#pragma vector = UART1_R_RXNE_vector
//__interrupt void uart1rxd(void)
//{
// data = UART1_DR;
//}
从机程序
#include"iostm8s103k3.h"
#include"led.h"
#include"delay.h"
uint m,flag;
void CLK_Init(void)
{
CLK_CKDIVR_HSIDIV = 0; //1分频
}
void GPIOC_Init(void)
{
/*一主一从高速模式(GPIO从模式)*/
PC_DDR=0x8f; //MISO为为高速推挽输出,MISO为悬空输入,SCK悬空输入
PC_CR1=0x8f;
PC_CR2=0x80;
}
void GPIO_Init(void)
{
PB_DDR=0xff; //MISO为悬空输入,MISO为高速推挽输出,SCK高速推挽输出
PB_CR1=0xff;
PB_CR2=0x00;
PD_DDR=0xff; //MISO为悬空输入,MISO为高速推挽输出,SCK高速推挽输出
PD_CR1=0xff;
PD_CR2=0x00;
}
void SPI_Init(void)
{
/*从模式SPI寄存器初始化*/
CLK_PCKENR1=0xff; //接通外设时钟门控制器
SPI_CR1=0x31;
SPI_CR2=0x02;
SPI_CR1|=0x40;
/* 高位先发,分频128,从机模式,空闲为低,第二时钟沿采样,双向单线模式内部使能
NSS管脚,禁止CRC*/
}
void Write_Byte(uchar byte)
{
SPI_DR = byte; /* 将发送的数据写到数据寄存器 */
while(!(SPI_SR & 0x02)); /* 等待发送寄存器为空 */
}
uchar Read_Write(uchar byte)
{
uchar Rvalue;
while(!(SPI_SR & 0x02)); /* 等待发送寄存器为空 */
delayus();
SPI_DR = byte; /* 发送一个无效字节,以产生接收时钟*/
while(!(SPI_SR & 0x01)); /* 等待接受寄存器满 */
delayus();
Rvalue=SPI_DR;
return Rvalue;
}
uchar Read_Byte()
{
uint Rvalue;
while(!(SPI_SR & 0x01)); /* 等待接受寄存器满 */
delayus();
Rvalue=SPI_DR;
return Rvalue;
}
int main(void)
{
asm("sim"); //关总中断
CLK_Init();
GPIOC_Init();
GPIO_Init();
SET_Init();
SPI_Init();
SPI_ICR=0X40;
asm("rim"); //开总中
while(1)
{
if(flag==1)
{
flag=0;
Write_Byte(m);
Display(1, m);
}
}
}
#pragma vector = 0xC
__interrupt void SPI_IRQHandler(void)
{
if((SPI_SR&0x01)==1)
{
m=Read_Byte();
flag=1;
}
//add your code hered
}
其单步调试时,从机把主机发送过来的数发回主机。通过UART口显示到上位机上(串口调试助手)
其串口接收的数据如下;00 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F 0B 0F
从机display的函数显示也正常,但是一旦主机debeg全速运行就会出错
主机通过UART口显示的是0B和0F显示就会不对。从机display的函数显示就不正常了。
可能是延时时间也可能是全速运行时display显示的是一部分。本人是想先通过写一个函数数给从机数,从机应答。如果成功了想写一组数函数发送给从机。再就是随时在主机接收一个数,接收一直数。请教高人stm8 的spi硬件通信(不是通过模拟的),。谢谢
由于是新人没有太多分 请见谅
|