MCP23S17是通过SPI接口同MPU连接。进行接口扩展,GPB6与GPB7引脚的按键可以控制GPA0~7及GPP0~1引脚连接的条形LED按不同方向滚动。
Proteus 仿真截图:
Atmel Studio6.2编译通过截图:
程序清单:
/*
* GccApplication30.c
*
* Created: 2014-12-8 21:25:56
* Author: Administrator
*/
#define F_CPU 4000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdint.h>
#define MCP_ADDR 0x40
#define IODIRA 0x00
#define IODIRB 0x01
#define GPPUB 0x0D
#define GPIOA 0x12
#define GPIOB 0x13
#define SPI_EN() PORTB &=~_BV(PB4)
#define SPI_DI() PORTB |= _BV(PB4)
uint8_t Demo_OP_No = 0;
void SPI_MasterInit()
{
DDRB = 0B10110000;PORTB = 0xFF;
SPCR |=_BV(SPE)|_BV(MSTR)|_BV(SPR0);
}
uint8_t SPI_Transmit(uint8_t dat)
{
SPDR = dat;
while(!(SPSR & _BV(SPIF)));
return SPDR;
}
void Write_MCP23S17(uint8_t Device_addr,uint8_t Reg_addr,uint8_t CD)
{
SPI_EN();
SPI_Transmit(Device_addr);
SPI_Transmit(Reg_addr);
SPI_Transmit(CD);
SPI_DI();
}
void Reda_MCP23S17(uint8_t Device_addr,uint8_t Reg_addr,uint8_t * Dat)
{
SPI_EN();
SPI_Transmit(Device_addr|0x01);
SPI_Transmit(Reg_addr);
*Dat=SPI_Transmit(0xFF);
SPI_DI();
}
void Initialise_MCP23S17()
{
Write_MCP23S17(MCP_ADDR,IODIRA,0x00);
Write_MCP23S17(MCP_ADDR,IODIRB,0xF0);
Write_MCP23S17(MCP_ADDR,GPIOA,0x00);
Write_MCP23S17(MCP_ADDR,GPIOB,0x00);
}
void Key_Handle()
{
uint8_t Key_Port_Status;
Reda_MCP23S17(MCP_ADDR,GPIOB,&Key_Port_Status);
if((Key_Port_Status & 0x80)==0x00)Demo_OP_No = 0;
else
if((Key_Port_Status & 0x40)==0x00)Demo_OP_No = 1;
}
int main(void)
{
uint8_t i; uint16_t Pattern;
DDRB = 0xFF;
SPI_MasterInit();
Initialise_MCP23S17();
while(1)
{
//TODO:: Please write your application code
if(Demo_OP_No == 0)
{
Pattern = 0xFFFE;
for(i=0;i<10;i++)
{
Write_MCP23S17(MCP_ADDR,GPIOA,(uint8_t)Pattern);
Write_MCP23S17(MCP_ADDR,GPIOB,(uint8_t)(Pattern>>8));
Pattern = Pattern << 1 | 0x0001;
Key_Handle();
if(Demo_OP_No != 0)break;
_delay_ms(10);
}
}
else
{
Pattern = 0x01FF;
for(i=0;i<10;i++)
{
Write_MCP23S17(MCP_ADDR,GPIOA,(uint8_t)Pattern);
Write_MCP23S17(MCP_ADDR,GPIOB,(uint8_t)(Pattern>>8));
Pattern = Pattern >> 1 | 0x0200;
Key_Handle();
if(Demo_OP_No != 1)break;
_delay_ms(10);
}
}
}
}
|