[AVR单片机] mega16的SPI通信问题

[复制链接]
 楼主| 此心向学 发表于 2010-7-24 22:36 | 显示全部楼层 |阅读模式
走过路过千万不要一笑而过……
向路过的各位大侠请教个问题:

小弟菜鸟只学过51汇编,没有学过C,没有学过AVR

现在要用到AVR,遇到点麻烦,请大侠帮帮忙,谢谢。。。

初来咋到,分不多,大家别嫌少,帮帮忙,3Q

atmega16和12位ADC的SPI通信,我弄了半天,也没有弄通,请大家帮忙看看程序:

ADC芯片资料在附件:mega16芯片:
菜鸟的程序:
AVR硬件SPI:
unsigned char Get_mcp3204_val(void)
{
unsigned int i;
  float j;
i = mcp3204_SPI();
j = (i*5)/4096;
//这里只取转换结果整数部分验证一下通信是否成功先
j = (unsigned char)j;
return(j);
}
unsigned int mcp3204_SPI(void)
{
unsigned int temp,temp1;
DDRB =(1<<PB7)|(~(1<<PB6))|(1<<PB5)|(1<<PB4);
PORTB = (1<<PB7)|(1<<PB6)|(~(1<<PB5))|(1<<PB4);
SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA)|(1<<SPR1)|(1<<SPR0);//
PORTB &=(~(1<<PB4));//启动通信
SPSR = 0x00;
SPDR = 0x07;//发送起始位和SGL,D2位
while(!SPSR&(1<<SPIF));
PORTB &=(1<<PB4);
SPSR = 0x00;
SPDR = 0x3f;//发送D1D0
while(!SPSR&(1<<SPIF));
SPSR = 0x00;
temp = SPDR;//接受高四位
while(!SPSR&(1<<SPIF));
SPSR = 0x00;
temp1 = SPDR;//接受低8位
while(!SPSR&(1<<SPIF));
PORTB &=(1<<PB4);
temp = (unsigned int)temp<<8;
temp = (unsigned int)((temp|temp1)&0x0fff);
return(temp);
}

软件模拟SPI:
#include<avr/io.h>
#include"delay.h"
#include"display.h"
#define CS PB4
#define DO PB6
#define DI PB5
#define CLK PB7
unsigned int SPI_mcp3204(void);
int main(void)
{
while(1)
{
  unsigned char temp;
  unsigned int m,n;
  m = SPI_mcp3204();
  n = (m*5)/4096;
  temp = (unsigned char)n;
  display(temp);
}
}
unsigned int SPI_mcp3204(void)
{
unsigned char j;
unsigned int i = 0;
DDRB = 0xbf;
PORTB = 0xff;
//发送启动位和SGL,D2,D1,D0
PORTB &=(~(1 << CS));
PORTB &=(~(1 << CLK));
PORTB &= (1<< DI);//1
PORTB &=(1 << CLK);
asm("nop");
PORTB &=(~(1 << CLK));
PORTB &= (1<< DI);//1
PORTB &=(1 << CLK);
asm("nop");
PORTB &=(~(1 << CLK));
PORTB &=(~(1 << DI));//0
PORTB &=(1 << CLK);
asm("nop");
PORTB &=(~(1 << CLK));
PORTB &=(~(1 << DI));//0
asm("nop");
PORTB &=(1 << CLK);
//采样周期
asm("nop");
PORTB &=(~(1 << CLK));
asm("nop");
PORTB &=(1 << CLK);
//空位
asm("nop");
PORTB &=(~(1 << CLK));
asm("nop");
PORTB &=(1 << CLK);
//读取转换结果
for(j =12;j > 0; j--)
{
  asm("nop");
  PORTB &=(~(1 << CLK));
  asm("nop");
  i = ((PINB&0x40) >> PB6);
  i <<=1;
  PORTB &=(1 << CLK);
}
PORTB &= (1 << CS);//拉高片选
i >>= 1;
return(i);
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| 此心向学 发表于 2010-7-24 22:41 | 显示全部楼层
图:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| 此心向学 发表于 2010-7-25 11:01 | 显示全部楼层
没人回答啊
宇宙飞船 发表于 2010-7-25 11:16 | 显示全部楼层
什么项目要用到12位的ADC?
是音频吗?音频要求的是16位精度,就算楼主想选用32位机,没有外挂ADC也无济于事。
若果是一般的项目,10位ADC也很好用了,楼主可否把项目的要求说明一下,俺可以帮忙分析一下硬件,看哪些地方可以优化,使最终使用一块MCU就能实现。
 楼主| 此心向学 发表于 2010-7-25 11:52 | 显示全部楼层
很不好意思啊,是我没有理解好AVR硬件的SPI,闹出了笑话。
下面把可以通信的程序贴出来:
unsigned int mcp3204_SPI(void)
{
        static unsigned int temp,temp1;
        DDRB =(1<<PB7)|(~(1<<PB6))|(1<<PB5)|(1<<PB4);
        PORTB = (1<<PB7)|(1<<PB6)|(1<<PB5)|(1<<PB4);
        SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA)|(1<<SPR1)|(1<<SPR0);//
        PORTB &=(~(1<<PB4));//启动通信
        temp = SPIWrite(0x07);
        temp = SPIWrite(0x3f);
        temp1 = SPIWrite(0xff);
        PORTB &=(1<<PB4);
        temp = (unsigned int)temp<<8;
        temp = (unsigned int)((temp|temp1)&0x0fff);
        return(temp);

}


unsigned char SPIWrite(unsigned char data)
{
                SPDR = data;
                while(!(SPSR & (1<<SPIF)));
          return (SPDR);
}
 楼主| 此心向学 发表于 2010-7-25 11:56 | 显示全部楼层
非常感谢版主,
要用到两路adc转换,分辨率至少要12位,速率也不能太慢,
估计后面还得用到两通道的12位DAC。
10位的分辨率不够。 4# 宇宙飞船
 楼主| 此心向学 发表于 2010-7-25 11:59 | 显示全部楼层
读取SPDR不能用temp = SPDR;
只能用return(SPDR);吗
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

70

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部