我是Avr编程的初学者,我有一个16位寄存器从器件(存储器芯片),我想通过Atmega328(8位寄存器)在存储器中读写,我知道我必须发送8 x 8位,我已经尝试过编程,但是我无法使用Atmel Studio调试器从我的奴隶那里读取,有人可以给我建议吗?
与我的芯片通信的协议是SPI。
串行通信在芯片的数据表中描述为:
要从chipi读取必须发送:
0x03 = 0b00000011: 8 bit READ command
0x0000 - 0x07FF = 0bXXXXXAAA AAAAAAAA: 16 bit ADDRESS (5 upper bits don't care)
然后我会收到:
0x0000 - 0xFFFF = 0bDDDDDDDD DDDDDDDD: 16 bit DATA
要写入我必须发送的芯片:
0x02 = 0b00000010: 8 bit WRITE command
0x0000 - 0x07FF = 0bXXXXXAAA AAAAAAAA: 16 bit ADDRESS (5 upper bits don't care)
0x0000 - 0xFFFF = 0bDDDDDDDD DDDDDDDD: 16 bit DATA
用户存储区从0x0000变为0xA6F。
在串行通信模式下,如果LSI在执行READ / WRITE命令时发生错误,则错误代码将存储在e SPI错误信息寄存器中。
Bit 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Function 0 0 0 0 0 0 0 0 0 0 0 0 | ERROR* |
* : ERROR
b1000 : Low voltage detection
b0100 : Write NG
b0010 : Read NG
b0001 : NG because RF occurred
b0000 : Finished successfully
我的SPI init是:
void spi_init()
// Initialize pins for spi communication
{
// set MOSI , select chip SS and SCK Output, all others are outputs
DDR_SPI |= ((1<<DD_MOSI)|(1<<DD_SCK) );/*|(1<<DD_SS))*/
// set MISO us input
//Enable SPI, Master, set clock rate
SPCR = (1<<SPE|(1<<MSTR)| (1<<SPR0)| // SPI Enable
(0<<SPIE)| // SPI Interrupt Enable
(0<<DORD)| // Data Order (0:MSB first / 1:LSB first)
(1<<MSTR)| // Master/Slave select
(0<<SPR1)|(1<<SPR0)| // SPI Clock Rate
(1<<CPOL)| // Clock Polarity (0:SCK low / 1:SCK hi when idle)
(1<<CPHA)); // Clock Phase (0:leading / 1:trailing edge sampling)
SPSR = (1<<SPI2X); // Double Clock Rate
}
void SPI_MasterTransmit(uint16_t cdata){
SPDR = cdata; //start transmission
while(!(SPSR & (1<<SPIF))); // wait for transmission complete
}
uint16_t SPI_SlaveReceive(void){
while(!(SPSR & (1<<SPIF))); //wait for reception complete
return (SPDR); //return Data Register
}
读:
uint16_t read_SPI( uint16_t address){
uint16_t datar;
Slave_select;
// charger les données inf au buffer
SPDR = uint16_t( address & 0xFF);
//attente lors de la premiere transmission
while(!(SPSR & (1<<SPIF) ));
// premier octet est reçu
datar = SPDR;
// charger les données sup au buffer
SPDR = uint16_t ((address >> 8) & 0xFF);
//attente de la seconde tr
while(!(SPSR & (1<<SPIF) ));
// seceond octet est reçu
datar = datar | ((uint16_t) (SPDR) << 8);
Slave_deselect;
return datar;
}
写
void write_SPI (uint16_t address, uint16_t data){
Slave_select;
SPDR= data;
while(!(SPSR & (1<<SPIF)));
/*data = SPDR;*/ // erase SPDR register
Slave_deselect;
}
答案 0 :(得分:0)
你永远不会发送命令,只发送地址的低8位。
粗略地说,ATmega侧的引脚设置应如下所示:
PORT? = (1u << MISO) | (1u << MOSI) | (1u << SCK) | (1u << CS);
DDR? = (1u << MOSI) | (1u << CS) | (1u << SCK);
/* pull-up on MISO, init all others idle high/active low */
然后读取函数是这样的:
uint16_t read_SPI( uint16_t address){
uint16_t res;
PORT? &= ~(1u << CS); /* assert #CS */
SPDR = 0x03u; /* READ command */
while(!(SPSR & (1<<SPIF) ));
SPDR = (address >> 8) & 0xFFu; /* high-order address bits */
while(!(SPSR & (1<<SPIF) ));
SPDR = (address >> 0) & 0xFFu; /* low-order address bits */
while(!(SPSR & (1<<SPIF) ));
SPDR = 0xFFu; /* dummy write to clock in high-order data bits */
while(!(SPSR & (1<<SPIF) ));
res = SPDR;
SPDR = 0xFFu; /* dummy write to clock in low-order data bits */
res <<= 8;
res = SPDR;
PORT? |= (1u << CS); /* deassert #CS */
return res;
}
请注意这是一个非常基本的示例,通常您不希望无限期地阻止微控制器等待SPI状态标志。但是,请考虑将此代码设置为可以可靠地读取和写入EEPROM的位置。然后,您可以添加一些抽象,并使用数据结构和基于中断的SPI例程来处理访问内存。