tangcangeng 发表于 2014-5-5 17:18:51

求助各位,AVR SPI接口读MAX6675结果不对的问题

各位 打扰大家了由于要用到热电偶进行温度控制 ,因此选了MAX6675,用AVR 的SPI口进行读MAX6675 发现读回来的数据不对,麻烦大家帮我看下是SPI接口哪个环节设置错误了 谢谢排查了两天了都没看出来~~ 下面是我的程序:

include<avr/io.h>
#include<avr/interrupt.h>//如果要用到外部中断,必须包含此头文件
void Init_SPI(void);
void init_USART(void);

//常量定义
#define BAUDRATE              9600        //波特率
#define F_CPU                                8000000 //这个已经在makefile里面定义了

unsigned char temperature,send_temp_ok=0;
void delay(void);
volatile unsigned char hbytedata,lbytedata;
unsigned int Read_Max6675(unsigned char c);

int main(void)
{

init_USART();
Init_SPI();
while(1)
{   
    temperature=Read_Max6675(0x00);
        if(send_temp_ok)
        {
        while ( !( UCSRA & (1<<UDRE)) )//在载入新的要发送的数据前,通过检测UDRE 标志等待发送缓冲器为空。该位在发送缓冲器空时被置"1” ;当发送缓冲器包含需要发送的数据时清零。
    ;
    UDR = temperature;/* 确认UDR空时,将数据放入缓冲器,然后将接收到的数据i发送回PC机子 */
//    while ( !( UCSRA & (1<<UDRE)) )//在载入新的要发送的数据前,通过检测UDRE 标志等待发送缓冲器为空。该位在发送缓冲器空时被置"1” ;当发送缓冲器包含需要发送的数据时清零。
//   ;
//    UDR = lbytedata;/* 确认UDR空时,将数据放入缓冲器,然后将接收到的数据i发送回PC机子 */
        send_temp_ok=0;
        }
}
}


void Init_SPI(void)
{
DDRB|=((1<<4)|(1<<5)|(1<<7));//PB4设置为输出,对应SPI的SS,PB5设置为输出,对应SPI的MOSI,PB7设置为输出,对应SPI的SCK
DDRB&=~(1<<6);//PB6设置为输入,对应SPI的MISO
PORTB|=(1<<6);//为PB6配置上拉电阻
SPCR|=((1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<SPR0));//使能SPI 中断,SPE 置位将使能SPI,MSTR置位时选择主机模式,下降沿为起始沿
SPCR&=~(1<<CPHA);//下降沿时主机、从机均采样数据,上升沿移位
SPSR|=(1<<SPI2X);//SPI速率为系统时钟8分频,即1M
SPCR&=~(1<<DORD);//DORD清零,数据的MSB 首先发送
}

void init_USART(void)//USART 初始化
{
//第一步:设置波特率
    //U2X=0时的公式计算
    UBRRL= (F_CPU/BAUDRATE/16-1)%256;
    UBRRH= (F_CPU/BAUDRATE/16-1)/256;
//第二步:使能发送、接收、接收完成中断:
//置位UCSRB 的接收结束中断使能位(RXCIE) 后,只要RXC 标志置位( 且全局中断使能
//) 就会产生USART 接收结束中断。使用中断方式进行数据接收时,数据接收结束中断服
//务程序程序必须从UDR 读取数据以清RXC 标志,否则只要中断处理程序一结束,一个
//新的中断就会产生。接收结束标志(RXC) 用来说明接收缓冲器中是否有未读出的数据。
    UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);//置位UCSRB 寄存器的发送允许位TXEN 将使能USART 的数据发送,置位UCSRB 寄存器的接收允许位(RXEN) 即可启动USART 接收器。
//第三步:
SREG|=(1<<7);//开总中断
}

unsigned int Read_Max6675(unsigned char c)
{
unsigned int temp=0x0000;

PORTB|=(1<<4);//启动一次转换处理过程
delay();//等待转换完成,大概需要0.2S左右
PORTB&=~(1<<4);//转换结束,将CS拉低停止转换处理
SPDR=c;//启动SPI,写的同时进行读取
while((SPSR&(1<<SPIF))==0);//SPI还没传输完成 等待
hbytedata=SPDR;//将数据的高8位保存起来
SPDR=c;//启动SPI,写的同时进行读取
while((SPSR&(1<<SPIF))==0);//SPI还没传输完成 等待
lbytedata=SPDR;//将数据的低8位保存起来
temp|=(hbytedata<<8);
temp|=lbytedata;
temp<<=1;
temp>>=4;
send_temp_ok=1;
return temp;
}

void delay(void)
{
unsigned int t1,t2;
for(t1=0;t1<550;t1++)
for(t2=0;t2<250;t2++)
asm("nop");
}


AVR也是刚学 所以如有什么不妥 请见谅~

tangcangeng 发表于 2014-5-5 17:21:06

自己顶一下先MAX6675看数据手册是下降沿的时候读取数据的吧??   我AVR中将SPI口设置为前沿是下降沿,然后下降沿读取数据,后一个沿即上升沿将MAX6675进行移位不知道对不?

sy_lixiang 发表于 2014-5-5 17:28:53

手头有示波器吗?看一下。

读不出数,多数是时序的事情。

temperature=Read_Max6675(0x00);

上边的0x00是寄存器地址吗?检查一下。

temp<<=1;
temp>>=4;

这是在干什么???
确认一下。

你要在线调一下,应该搞得定的。

tangcangeng 发表于 2014-5-6 08:10:54

首先感谢3楼的回复估计3楼没自己看函数体吧0x00是随便写的一个数,AVR 的SPI 写进去的同时是对从机进行读的而MAX6675只是一个传感器带AD的 只需读就可以了所以我随便写了一个数以启动AVR 的SPI读。   
请各位有用过AVR SPI的 帮忙一下吧顺带附上MAX6675的时序

tangcangeng 发表于 2014-5-6 08:11:57

本帖最后由 tangcangeng 于 2014-5-6 08:21 编辑

sy_lixiang 发表于 2014-5-5 17:28
手头有示波器吗?看一下。

读不出数,多数是时序的事情。


首先感谢3楼的回复估计3楼没自己看函数体吧0x00是随便写的一个数,AVR 的SPI 写进去的同时是对从机进行读的而MAX6675只是一个传感器带AD的 只需读就可以了所以我随便写了一个数以启动AVR 的SPI读。   
请各位有用过AVR SPI的 帮忙一下吧顺带附上MAX6675的时序,因为MAX6675一次读过来的温度数据是16位的而最高位15 以及低3位都是跟温度无关的, 所以左移1位去掉最高位右移4位去掉最低3位以及由最先的左移1位的补零,剩下的3-14位就是有效位了


tangcangeng 发表于 2014-5-12 16:55:32

谢谢各位 已经解决了AVR 的SPI接口还是很好用的 只是比较难懂
页: [1]
查看完整版本: 求助各位,AVR SPI接口读MAX6675结果不对的问题