AVR has only one SPI interface. If you want to drive more peripherals with SPI interface, you must simulate them through IO. In fact, IO simulation is also very convenient for low-speed peripherals. There are many programs for simulating SPI on the Internet. My program is written based on GCCAVR. Other compilers are similar. When writing, I try to be standardized and convenient for modification and adjustment in later use.
The following points should be noted when using:
1. According to the timing requirements of the peripherals, distinguish whether to update data on the rising edge or the falling edge.
2. When sending data, should the high bit come first or the low bit come first?
3. Whether the peripheral has speed requirements for SPI communication. Sometimes, too fast a communication rate may not be able to read and write data.
4. Normal level of CLK, data and other pins
The above points can be understood at a glance by comparing them with the timing diagram of the peripherals. The program is clearly written and you can just make the corresponding changes.
The procedure is as follows:
/******************************(C) COPYRIGHT emouse 2011********************** **********
Name: main.c
Function: Simulate SPI program test
Author:emouse
Date: 2011.1.11
Version: 1.0
Note: None
*************************************************** *******************************/
#include "avr/io.h"
#include "avr/interrupt.h"
#include "util/delay.h"
#define SetBit(Port,N) (Port|=(1< #define ClrBit(Port,N) (Port&=~(1< #define ReverBit(Port,N) (Port^=(1< #define GetBit(Pin,N) ((Pin>>N)&0x01) //Read a certain bit of IO /***************Related macro definitions for simulating SPI************************/ #define SPI1_Port PORTC //Set the port used #define SPI1_DDR DDRC #define SPI1_PIN PINC #define SPI1_CS 0 //Set the pin corresponding to each signal #define SPI1_MISO 1 #define SPI1_MOSI 2 #define SPI1_CLK 3 #define SPI1_CS_H (SPI1_Port|=(1< #define SPI1_CS_L (SPI1_Port&=~(1< #define SPI1_GetMISO ((SPI1_PIN>>SPI1_MISO)&0x01) #define SPI1_MOSI_H (SPI1_Port|=(1< #define SPI1_MOSI_L (SPI1_Port&=~(1< #define SPI1_CLK_H (SPI1_Port|=(1< #define SPI1_CLK_L (SPI1_Port&=~(1< unsigned char spi_delay; //Set the duration of the signal, which is equivalent to setting the speed of SPI /****************************************************** **************************** Name: void SPI1_Init() Function: Simulate SPI timing port initialization Parameters: None Date: 2011.1.11 Version: 1.0 Note: None *************************************************** *******************************/ void SPI1_Init() { SPI1_Port|=((1< SPI1_DDR|=(((1< SPI1_CS_H; SPI1_CLK_L; spi_delay=5; } /****************************************************** **************************** Name: SPI1_Send(unsigned char data) Function: Send SPI data Parameter: unsigned char data Date: 2011.1.11 Version: 1.0 Note: None *************************************************** *******************************/ void SPI1_Send(unsigned char data) { unsigned char i; SPI1_CS_L; //Pull the chip select signal low SPI1_CLK_L; //The clock is low when idle SPI1_MOSI_L; _delay_us(spi_delay); for(i=0;i<8;i++) { if(data&(0x80>>i))//high bit first, low bit first change to (0x01< SPI1_MOSI_H; else SPI1_MOSI_L; _delay_us(spi_delay); SPI1_CLK_H; //Update data on the rising edge _delay_us(spi_delay); SPI1_CLK_L; } _delay_us(spi_delay); SPI1_CS_H; //Pull up the chip select to complete a data transmission } /****************************************************** **************************** Name: unsigned char SPI1_Get() Function: Receive SPI data Parameter: return data Date: 2011.1.11 Version: 1.0 Note: None *************************************************** *******************************/ unsigned char SPI1_Get() { unsigned char i; unsigned char data=0x00; SPI1_CS_L; //Pull the chip select signal low SPI1_CLK_L; //The clock is low when idle SPI1_MOSI_L; _delay_us(spi_delay); for(i=0;i<8;i++) { if(SPI1_GetMISO) data|=(0x80>>i); _delay_us(spi_delay); SPI1_CLK_H; //Update data on the rising edge _delay_us(spi_delay); SPI1_CLK_L; } _delay_us(spi_delay); SPI1_CS_H; //Pull up the chip select to complete a data transmission return data; } /****************************************************** **************************** Name: void USART0_Init(void) Function: Initialize serial port 0 Parameters: None Date: 2011.1.11 Version: 1.0 Note: None *************************************************** *******************************/ void USART0_Init(void) { UCSR0A=0x20; //Baud rate is not doubled, single machine communication mode UCSR0B=0x18; //Interrupt disabled, sending and receiving allowed UCSR0C = 0x06; //Asynchronous mode, no check, 8-bit data, 1 stop bit UBRR0H=0x00; UBRR0L=51; //9600 baud rate, crystal oscillator 8M } /****************************************************** **************************** Name: void USART0_Putc(unsigned char c) Function: Send a character Parameter: unsigned char c Date: 2011.1.11 Version: 1.0 Note: None *************************************************** *******************************/ void USART0_Putc(unsigned char c) { while(!(UCSR0A&(1< UDR0=c; //Send data } /****************************************************** **************************** Name: void USART0_Puts(unsigned char * str) Function: Send string Parameter: unsigned char * str string to be sent Date: 2011.1.11 Version: 1.0 Note: None *************************************************** *******************************/ void USART0_Puts(unsigned char * str) { while(*str) { USART0_Putc(*str++); } } int main(void) { unsigned char i=0; USART0_Init(); //Initialize USART0 interface DDRA=0XFF; PORTA=0XFF; SPI1_Init(); USART0_Puts("SPI test"); while(1) { SPI1_Send(0x04); USART0_Putc(SPI1_Get()); ReverBit(PORTA,0); _delay_ms(500); } }
Previous article:CPLD and AVR communication PWM control program
Next article:AVR Assembly Program Part 1: The Internal Structure of the AVR MCU's CPU
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Innovation is not limited to Meizhi, Welling will appear at the 2024 China Home Appliance Technology Conference
- Innovation is not limited to Meizhi, Welling will appear at the 2024 China Home Appliance Technology Conference
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- [AD21] How to solve the error Board Clearance Constraint
- Read the good book "Operational Amplifier Parameter Analysis and LTspice Application Simulation" + Reading to learn about amplifiers
- Can anyone make a 433M remote control?
- 【DFRobot Wireless Communication Module】+ DFRobot Gravity: UART A6 GSM & GPRS Wireless Communication Module Review
- Creative PCB display
- LPC2478 Timer 2 and Timer 3 enable
- Design and implementation of optical transceiver UART interface based on FPGA.pdf
- MicroPython official new wiki
- Is this setting OK?
- Daisy chain communication