记录基于stm32f103vet6调试工作。
调试工程是在正点原子网络通信实验上做的修改,该例程使用的是stm32f103zet6主控,144pin。
主要修改为FSMC总线的管脚重定义,按照硬件给的原理图对照着来就行,需要注意的是例程里使用的是NE2,而我们使用的主控是没有这的,只能使用NE1,在初始化的时候注意使用BANK1NE1。例程使用的是FSMC_A7,我们主控同样没有这个定义,只能用FSMC_A16或者FSMC_A17,我们使用的是FSMC_A17,所以在操作总线的基地址要按照规则做修改。
//初始化DM9000
//返回值:
//0,初始化成功
//1,DM9000A ID读取错误
u8 DM9000_Init(void)
{
u32 temp;
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
FSMC_NORSRAMTimingInitTypeDef ReadWriteTiming; //DM9000的读写时序
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE,ENABLE); //使能GPIOD E 时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE); //使能FSMC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能复用功能时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PD2 推挽输出 reset
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//推挽输出
GPIO_Init(GPIOD,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //PC6 推挽输出 int
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
GPIO_Init(GPIOC,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 | // FSMC_D0
GPIO_Pin_15 | // FSMC_D1
GPIO_Pin_0 | // FSMC_D2
GPIO_Pin_1 | // FSMC_D3
GPIO_Pin_8 | // FSMC_D13
GPIO_Pin_9 | // FSMC_D14
GPIO_Pin_10 ; // FSMC_D15
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Init(GPIOD,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | // FSMC_D4
GPIO_Pin_8 | // FSMC_D5
GPIO_Pin_9 | // FSMC_D6
GPIO_Pin_10 | // FSMC_D7
GPIO_Pin_11 | // FSMC_D8
GPIO_Pin_12 | // FSMC_D9
GPIO_Pin_13 | // FSMC_D10
GPIO_Pin_14 | // FSMC_D11
GPIO_Pin_15 ; // FSMC_D12
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Init(GPIOE,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //PD12复用 CMD
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Init(GPIOD,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //PD7复用 NE1
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Init(GPIOD,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //PD4复用 FSMC_NOE
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Init(GPIOD,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //PD5复用 FSMC_NWE
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
GPIO_Init(GPIOD,&GPIO_InitStructure);
//PG6外部中断,中断线6
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource6);
EXTI_InitStructure.EXTI_Line = EXTI_Line6;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
EXTI_ClearITPendingBit(EXTI_Line6); //清除中断线6挂起标志位
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //外部中断线6
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
ReadWriteTiming.FSMC_AddressSetupTime = 0; //地址建立时间
ReadWriteTiming.FSMC_AddressHoldTime = 0;
ReadWriteTiming.FSMC_DataSetupTime = 3; //数据建立时间
ReadWriteTiming.FSMC_BusTurnAroundDuration = 0x00;
ReadWriteTiming.FSMC_CLKDivision = 0x00;
ReadWriteTiming.FSMC_DataLatency = 0x00;
ReadWriteTiming.FSMC_AccessMode = FSMC_AccessMode_A;//使用模式A
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1; //NE1
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &ReadWriteTiming;
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &ReadWriteTiming;
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1,ENABLE); //使能FSMC的Bank1_Bank1_NORSRAM1
temp=*(vu32*)(0x1FFFF7E8); //获取STM32的唯一ID的前24位作为MAC地址后三字节
dm9000cfg.mode=DM9000_AUTO;
dm9000cfg.queue_packet_len=0;
//DM9000的SRAM的发送和接收指针自动返回到开始地址,并且开启接收中断
dm9000cfg.imr_all = IMR_PAR|IMR_PRI;
//初始化MAC地址
dm9000cfg.mac_addr[0]=2;
dm9000cfg.mac_addr[1]=0;
dm9000cfg.mac_addr[2]=0;
dm9000cfg.mac_addr[3]=(temp>>16)&0XFF; //低三字节用STM32的唯一ID
dm9000cfg.mac_addr[4]=(temp>>8)&0XFFF;
dm9000cfg.mac_addr[5]=temp&0XFF;
//初始化组播地址
dm9000cfg.multicase_addr[0]=0Xff;
dm9000cfg.multicase_addr[1]=0Xff;
dm9000cfg.multicase_addr[2]=0Xff;
dm9000cfg.multicase_addr[3]=0Xff;
dm9000cfg.multicase_addr[4]=0Xff;
dm9000cfg.multicase_addr[5]=0Xff;
dm9000cfg.multicase_addr[6]=0Xff;
dm9000cfg.multicase_addr[7]=0Xff;
DM9000_Reset(); //复位DM9000
delay_ms(100);
temp=DM9000_Get_DeiviceID(); //获取DM9000ID
printf("DM9000 ID:%#x\r\n",temp);
if(temp!=DM9000_ID) return 1; //读取ID错误
DM9000_Set_PHYMode(dm9000cfg.mode); //设置PHY工作模式
DM9000_WriteReg(DM9000_NCR,0X00);
DM9000_WriteReg(DM9000_TCR,0X00); //发送控制寄存器清零
DM9000_WriteReg(DM9000_BPTR,0X3F);
DM9000_WriteReg(DM9000_FCTR,0X38);
DM9000_WriteReg(DM9000_FCR,0X00);
DM9000_WriteReg(DM9000_SMCR,0X00); //特殊模式
DM9000_WriteReg(DM9000_NSR,NSR_WAKEST|NSR_TX2END|NSR_TX1END);//清除发送状态
DM9000_WriteReg(DM9000_ISR,0X0F); //清除中断状态
DM9000_WriteReg(DM9000_TCR2,0X80); //切换LED到mode1
//设置MAC地址和组播地址
DM9000_Set_MACAddress(dm9000cfg.mac_addr); //设置MAC地址
DM9000_Set_Multicast(dm9000cfg.multicase_addr); //设置组播地址
DM9000_WriteReg(DM9000_RCR,RCR_DIS_LONG|RCR_DIS_CRC|RCR_RXEN);
DM9000_WriteReg(DM9000_IMR,IMR_PAR);
temp=DM9000_Get_SpeedAndDuplex(); //获取DM9000的连接速度和双工状态
if(temp!=0XFF) //连接成功,通过串口显示连接速度和双工状态
{
printf("DM9000 Speed:%dMbps,Duplex:%s duplex mode\r\n",(temp&0x02)?10:100,(temp&0x01)?"Full":"Half");
}else printf("DM9000 Establish Link Failed!\r\n");
DM9000_WriteReg(DM9000_IMR,dm9000cfg.imr_all); //设置中断
return 0;
}
#define DM9000_RST PDout(2) //DM9000复位引脚
#define DM9000_INT PCin(6) //DM9000中断引脚
//DM9000地址结构体
typedef struct
{
vu16 REG;
vu16 DATA;
}DM9000_TypeDef;
//使用NOR/SRAM的 Bank1.sector1,地址位HADDR[27,26]=01 A17作为数据命令区分线
//注意设置时STM32内部会右移一位对其!
#define DM9000_BASE ((u32)(0x60000000|0x0003FFFE)) //A17 作为数据命令分线
#define DM9000 ((DM9000_TypeDef *) DM9000_BASE)