这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » (SD卡+FATFS,进行中)zangchao ARM DIY进程帖

共124条 12/13 |‹ 8 9 10 11 12 13 跳转至
高工
2012-06-15 22:07:25     打赏
111楼
你完成的试验也不少啊,呵呵

工程师
2012-06-15 22:13:04     打赏
112楼

CRC循环冗余实验是利用STM32内部的CRC校验电路对数组中数进行CRC校验。然后将CRC校验码通过USART1(PA9,PA10)在串口助手上显示出来。


关于代码部分就很简单了,CRC配置部分,只需要打开CRC的时钟就可以了。
void CRC_Config(void)
{
 /* Enable CRC clock */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);
}

主函数部分,就是将数组中的数据送给CRC就可以了
int main(void)
{
  u8 i = 0;

 /* config the sysclock to 72M */     
  RCC_Configuration();

  /* USART1 config */
 USART1_Config();

 /* 使能CRC时钟 */
 CRC_Config();

 printf("\r\n 这是一个 CRC(循环冗余校验)实验 \r\n");

    /* Compute the CRC of "DataBuffer" */
 for(i=0; i<BUFFER_SIZE; i++ )
 {
  CRCValue = CRC_CalcBlockCRC((uint32_t *)DataBuffer, BUFFER_SIZE);
  printf("\r\n32-bit CRC 校验码为:0X%X\r\n", CRCValue);
 }
  printf("\r\nCRC(循环冗余校验)测试成功\r\n");

  while (1)
  {     
  }
}


工程师
2012-06-15 22:23:42     打赏
113楼

每个芯片都有唯一的ID,就如同每个网卡都有唯一的MAC地址一样,本实验就是读取自己的STM32F103ZET的ID号。如下图所示,大家可以看见我的芯片ID号:

这里给出获取ID号的函数,其实就是获得固定地址(这个地址就是ID号的地址)中的数据。然后调用串口发送程序,也就发送ID到串口助手上显示。
void Get_ChipID(void)
{
 ChipUniqueID[0] = *(__IO u32 *)(0X1FFFF7F0); // 高字节
 ChipUniqueID[1] = *(__IO u32 *)(0X1FFFF7EC); //
 ChipUniqueID[2] = *(__IO u32 *)(0X1FFFF7E8); // 低字节
}


工程师
2012-06-15 22:32:31     打赏
114楼

哎,不多啊,就这么几个啊。明天考六级了,没有时间更新帖子了,今晚把自己做完的尽量更新吧,校园是无线网,每次考试都断网,估计得到下周一才能开网,所以怕没有更新帖子悲催了。


工程师
2012-06-15 23:14:53     打赏
115楼

ADC模数转换实验,当初自己搞起来不是很顺手,后来移植野火的例程,看了一遍工作过程,还是比较简单的,主要就是配置工作方式。因为手头上没有合适的外部模拟信号,这里我仅仅给定了0V和3.3V的电源输入。然后,将转换后的数字数据输出到串口助手上面。

下面附上ADC的配置代码,如下:

/*
 * 函数名:ADC1_GPIO_Config
 * 描述  :使能ADC1和DMA1的时钟,初始化PC.01
 * 输入  : 无
 * 输出  :无
 * 调用  :内部调用
 */
static void ADC1_GPIO_Config(void)
{
 GPIO_InitTypeDef GPIO_InitStructure;

 /* Enable DMA clock */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

 /* Enable ADC1 and GPIOC clock */
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);

  /* Configure PC.01  as analog input */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOC, &GPIO_InitStructure);    // PC1,输入时不用设置速率
}


/* 函数名:ADC1_Mode_Config
 * 描述  :配置ADC1的工作模式为MDA模式
 * 输入  : 无
 * 输出  :无
 * 调用  :内部调用
 */
static void ADC1_Mode_Config(void)
{
 DMA_InitTypeDef DMA_InitStructure;
 ADC_InitTypeDef ADC_InitStructure;

 /* DMA channel1 configuration */
  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = 1;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
 
  /* Enable DMA channel1 */
  DMA_Cmd(DMA1_Channel1, ENABLE);
    
  /* ADC1 configuration */
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 1;
  ADC_Init(ADC1, &ADC_InitStructure);

  /* ADC1 regular channel11 configuration */
  ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_55Cycles5);

  /* Enable ADC1 DMA */
  ADC_DMACmd(ADC1, ENABLE);
 
  /* Enable ADC1 */
  ADC_Cmd(ADC1, ENABLE);

  /* Enable ADC1 reset calibaration register */  
  ADC_ResetCalibration(ADC1);
  /* Check the end of ADC1 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC1));

  /* Start ADC1 calibaration */
  ADC_StartCalibration(ADC1);
  /* Check the end of ADC1 calibration */
  while(ADC_GetCalibrationStatus(ADC1));
    
  /* Start ADC1 Software Conversion */
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}


工程师
2012-06-15 23:22:01     打赏
116楼

PWM波形发生,就是利用TIMx来实现的。这里本实验使用定时器TIM3产生四路PWM波输出。使用的四路输出通道是:
PA.06: (TIM3_CH1)
PA.07: (TIM3_CH2)
PB.00: (TIM3_CH3)
PB.01: (TIM3_CH4) 

由于我手头现在没有示波器,现在去实验室借用示波器来演示的话,也来不及了,也就使用MDK软件模拟仿真吧。

下面附上TIM3的配置代码,这里是参考野火的例程。
/*
 * 函数名:TIM3_GPIO_Config
 * 描述  :配置TIM3复用输出PWM时用到的I/O
 * 输入  :无
 * 输出  :无
 * 调用  :内部调用
 */
static void TIM3_GPIO_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

 /* TIM3 clock enable */
 //PCLK1经过2倍频后作为TIM3的时钟源等于36MHz
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

  /* GPIOA and GPIOB clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);

  /*GPIOA Configuration: TIM3 channel 1 and 2 as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;      // 复用推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /*GPIOB Configuration: TIM3 channel 3 and 4 as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0 | GPIO_Pin_1;

  GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/*
 * 函数名:TIM3_Mode_Config
 * 描述  :配置TIM3输出的PWM信号的模式,如周期、极性、占空比
 * 输入  :无
 * 输出  :无
 * 调用  :内部调用
 */
static void TIM3_Mode_Config(void)
{
 TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
 TIM_OCInitTypeDef  TIM_OCInitStructure;

 /* PWM信号电平跳变值 */
 u16 CCR1_Val = 500;       
 u16 CCR2_Val = 375;
 u16 CCR3_Val = 250;
 u16 CCR4_Val = 125;

/* -----------------------------------------------------------------------
    TIM3 Configuration: generate 4 PWM signals with 4 different duty cycles:
    TIM3CLK = 36 MHz, Prescaler = 0x0, TIM3 counter clock = 36 MHz
    TIM3 ARR Register = 999 => TIM3 Frequency = TIM3 counter clock/(ARR + 1)
    TIM3 Frequency = 36 KHz.
    TIM3 Channel1 duty cycle = (TIM3_CCR1/ TIM3_ARR)* 100 = 50%
    TIM3 Channel2 duty cycle = (TIM3_CCR2/ TIM3_ARR)* 100 = 37.5%
    TIM3 Channel3 duty cycle = (TIM3_CCR3/ TIM3_ARR)* 100 = 25%
    TIM3 Channel4 duty cycle = (TIM3_CCR4/ TIM3_ARR)* 100 = 12.5%
  ----------------------------------------------------------------------- */

  /* Time base configuration */  
  TIM_TimeBaseStructure.TIM_Period = 999;       //当定时器从0计数到999,即为1000次,为一个定时周期
  TIM_TimeBaseStructure.TIM_Prescaler = 0;     //设置预分频:不预分频,即为36MHz
  TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分频系数:不分频
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //向上计数模式

  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  /* PWM1 Mode configuration: Channel1 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;     //配置为PWM模式1
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
  TIM_OCInitStructure.TIM_Pulse = CCR1_Val;    //设置跳变值,当计数器计数到这个值时,电平发生跳变
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  //当定时器计数值小于CCR1_Val时为高电平

  TIM_OC1Init(TIM3, &TIM_OCInitStructure);  //使能通道1

  TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);

  /* PWM1 Mode configuration: Channel2 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR2_Val;   //设置通道2的电平跳变值,输出另外一个占空比的PWM

  TIM_OC2Init(TIM3, &TIM_OCInitStructure);   //使能通道2

  TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);

  /* PWM1 Mode configuration: Channel3 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR3_Val; //设置通道3的电平跳变值,输出另外一个占空比的PWM

  TIM_OC3Init(TIM3, &TIM_OCInitStructure);  //使能通道3

  TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);

  /* PWM1 Mode configuration: Channel4 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR4_Val; //设置通道4的电平跳变值,输出另外一个占空比的PWM

  TIM_OC4Init(TIM3, &TIM_OCInitStructure); //使能通道4

  TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);

  TIM_ARRPreloadConfig(TIM3, ENABLE);    // 使能TIM3重载寄存器ARR

  /* TIM3 enable counter */
  TIM_Cmd(TIM3, ENABLE);                   //使能定时器3 
}


工程师
2012-06-15 23:49:34     打赏
117楼

AT24C02的读写,相信大家都用过51单片机实现过,就是IIC总线操作。这里通过STM32来实现,个人理解没有很大的区别和难度,只要弄好AT24C02的驱动也就完事了(当然是废话了,外设操作都是搞驱动函数的啦)
附上自己的实验图片(参考野火的驱动就非常简单了):


例行附上AT24C02的配置代码,如下:

/*
 * 函数名:I2C_GPIO_Config
 * 描述  :I2C1 I/O配置
 * 输入  :无
 * 输出  :无
 * 调用  :内部调用
 */
static void I2C_GPIO_Config(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;

 /* 使能与 I2C1 有关的时钟 */
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE); 
   
  /* PB6-I2C1_SCL、PB7-I2C1_SDA*/
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;        // 开漏输出
  GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/*
 * 函数名:I2C_Configuration
 * 描述  :I2C 工作模式配置
 * 输入  :无
 * 输出  :无
 * 调用  :内部调用
 */
static void I2C_Mode_Configu(void)
{
  I2C_InitTypeDef  I2C_InitStructure;

  /* I2C 配置 */
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
  I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7;
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;
 
  /* 使能 I2C1 */
  I2C_Cmd(I2C1, ENABLE);

  /* I2C1 初始化 */
  I2C_Init(I2C1, &I2C_InitStructure);

 /*允许1字节1应答模式*/
 I2C_AcknowledgeConfig(I2C1, ENABLE);   
}

/*
 * 函数名:I2C_EE_Init
 * 描述  :I2C 外设(EEPROM)初始化
 * 输入  :无
 * 输出  :无
 * 调用  :外部调用
 */
void I2C_EE_Init(void)
{

  I2C_GPIO_Config();
 
  I2C_Mode_Configu();

/* 根据头文件i2c_ee.h中的定义来选择EEPROM要写入的地址 */
#ifdef EEPROM_Block0_ADDRESS
  /* 选择 EEPROM Block0 来写入 */
  EEPROM_ADDRESS = EEPROM_Block0_ADDRESS;
#endif

#ifdef EEPROM_Block1_ADDRESS 
 /* 选择 EEPROM Block1 来写入 */
  EEPROM_ADDRESS = EEPROM_Block1_ADDRESS;
#endif

#ifdef EEPROM_Block2_ADDRESS 
 /* 选择 EEPROM Block2 来写入 */
  EEPROM_ADDRESS = EEPROM_Block2_ADDRESS;
#endif

#ifdef EEPROM_Block3_ADDRESS 
 /* 选择 EEPROM Block3 来写入 */
  EEPROM_ADDRESS = EEPROM_Block3_ADDRESS;
#endif
}

/*
 * 函数名:I2C_EE_BufferWrite
 * 描述  :将缓冲区中的数据写到I2C EEPROM中
 * 输入  :-pBuffer 缓冲区指针
 *         -WriteAddr 接收数据的EEPROM的地址
 *         -NumByteToWrite 要写入EEPROM的字节数
 * 输出  :无
 * 返回  :无
 * 调用  :外部调用
 */
void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)
{
  u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;

  Addr = WriteAddr % I2C_PageSize;
  count = I2C_PageSize - Addr;
  NumOfPage =  NumByteToWrite / I2C_PageSize;
  NumOfSingle = NumByteToWrite % I2C_PageSize;
 
  /* If WriteAddr is I2C_PageSize aligned  */
  if(Addr == 0)
  {
    /* If NumByteToWrite < I2C_PageSize */
    if(NumOfPage == 0)
    {
      I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      I2C_EE_WaitEepromStandbyState();
    }
    /* If NumByteToWrite > I2C_PageSize */
    else 
    {
      while(NumOfPage--)
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);
     I2C_EE_WaitEepromStandbyState();
        WriteAddr +=  I2C_PageSize;
        pBuffer += I2C_PageSize;
      }

      if(NumOfSingle!=0)
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
        I2C_EE_WaitEepromStandbyState();
      }
    }
  }
  /* If WriteAddr is not I2C_PageSize aligned  */
  else
  {
    /* If NumByteToWrite < I2C_PageSize */
    if(NumOfPage== 0)
    {
      I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      I2C_EE_WaitEepromStandbyState();
    }
    /* If NumByteToWrite > I2C_PageSize */
    else
    {
      NumByteToWrite -= count;
      NumOfPage =  NumByteToWrite / I2C_PageSize;
      NumOfSingle = NumByteToWrite % I2C_PageSize; 
     
      if(count != 0)
      { 
        I2C_EE_PageWrite(pBuffer, WriteAddr, count);
        I2C_EE_WaitEepromStandbyState();
        WriteAddr += count;
        pBuffer += count;
      }
     
      while(NumOfPage--)
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize);
        I2C_EE_WaitEepromStandbyState();
        WriteAddr +=  I2C_PageSize;
        pBuffer += I2C_PageSize; 
      }
      if(NumOfSingle != 0)
      {
        I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);
        I2C_EE_WaitEepromStandbyState();
      }
    }
  } 
}

/*
 * 函数名:I2C_EE_ByteWrite
 * 描述  :写一个字节到I2C EEPROM中
 * 输入  :-pBuffer 缓冲区指针
 *         -WriteAddr 接收数据的EEPROM的地址
 * 输出  :无
 * 返回  :无
 * 调用  :外部调用
 */
void I2C_EE_ByteWrite(u8* pBuffer, u8 WriteAddr)
{
  /* Send STRAT condition */
  I2C_GenerateSTART(I2C1, ENABLE);

  /* Test on EV5 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); 

  /* Send EEPROM address for write */
  I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);
 
  /* Test on EV6 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
     
  /* Send the EEPROM's internal address to write to */
  I2C_SendData(I2C1, WriteAddr);
 
  /* Test on EV8 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

  /* Send the byte to be written */
  I2C_SendData(I2C1, *pBuffer);
  
  /* Test on EV8 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
 
  /* Send STOP condition */
  I2C_GenerateSTOP(I2C1, ENABLE);
}

/*
 * 函数名:I2C_EE_PageWrite
 * 描述  :在EEPROM的一个写循环中可以写多个字节,但一次写入的字节数
 *         不能超过EEPROM页的大小。AT24C02每页有8个字节。
 * 输入  :-pBuffer 缓冲区指针
 *         -WriteAddr 接收数据的EEPROM的地址
 *         -NumByteToWrite 要写入EEPROM的字节数
 * 输出  :无
 * 返回  :无
 * 调用  :外部调用
 */
void I2C_EE_PageWrite(u8* pBuffer, u8 WriteAddr, u8 NumByteToWrite)
{
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); // Added by Najoua 27/08/2008
   
  /* Send START condition */
  I2C_GenerateSTART(I2C1, ENABLE);
 
  /* Test on EV5 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
 
  /* Send EEPROM address for write */
  I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);
 
  /* Test on EV6 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); 

  /* Send the EEPROM's internal address to write to */   
  I2C_SendData(I2C1, WriteAddr); 

  /* Test on EV8 and clear it */
  while(! I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

  /* While there is data to be written */
  while(NumByteToWrite--) 
  {
    /* Send the current byte */
    I2C_SendData(I2C1, *pBuffer);

    /* Point to the next byte to be written */
    pBuffer++;
 
    /* Test on EV8 and clear it */
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  }

  /* Send STOP condition */
  I2C_GenerateSTOP(I2C1, ENABLE);
}


/*
 * 函数名:I2C_EE_BufferRead
 * 描述  :从EEPROM里面读取一块数据。
 * 输入  :-pBuffer 存放从EEPROM读取的数据的缓冲区指针。
 *         -WriteAddr 接收数据的EEPROM的地址。
 *         -NumByteToWrite 要从EEPROM读取的字节数。
 * 输出  :无
 * 返回  :无
 * 调用  :外部调用
 */
void I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead)

  //*((u8 *)0x4001080c) |=0x80;
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); // Added by Najoua 27/08/2008
   
   
  /* Send START condition */
  I2C_GenerateSTART(I2C1, ENABLE);
  //*((u8 *)0x4001080c) &=~0x80;
 
  /* Test on EV5 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

  /* Send EEPROM address for write */
  I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);

  /* Test on EV6 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
 
  /* Clear EV6 by setting again the PE bit */
  I2C_Cmd(I2C1, ENABLE);

  /* Send the EEPROM's internal address to write to */
  I2C_SendData(I2C1, ReadAddr); 

  /* Test on EV8 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
 
  /* Send STRAT condition a second time */ 
  I2C_GenerateSTART(I2C1, ENABLE);
 
  /* Test on EV5 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
 
  /* Send EEPROM address for read */
  I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Receiver);
 
  /* Test on EV6 and clear it */
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
 
  /* While there is data to be read */
  while(NumByteToRead) 
  {
    if(NumByteToRead == 1)
    {
      /* Disable Acknowledgement */
      I2C_AcknowledgeConfig(I2C1, DISABLE);
     
      /* Send STOP Condition */
      I2C_GenerateSTOP(I2C1, ENABLE);
    }

    /* Test on EV7 and clear it */
    if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)) 
    {     
      /* Read a byte from the EEPROM */
      *pBuffer = I2C_ReceiveData(I2C1);

      /* Point to the next location where the byte read will be saved */
      pBuffer++;
     
      /* Decrement the read bytes counter */
      NumByteToRead--;       
    }  
  }

  /* Enable Acknowledgement to be ready for another reception */
  I2C_AcknowledgeConfig(I2C1, ENABLE);
}


/*
 * 函数名:I2C_EE_WaitEepromStandbyState
 * 描述  :Wait for EEPROM Standby state
 * 输入  :无
 * 输出  :无
 * 返回  :无
 * 调用  :
 */
void I2C_EE_WaitEepromStandbyState(void)     
{
  vu16 SR1_Tmp = 0;

  do
  {
    /* Send START condition */
    I2C_GenerateSTART(I2C1, ENABLE);
    /* Read I2C1 SR1 register */
    SR1_Tmp = I2C_ReadRegister(I2C1, I2C_Register_SR1);
    /* Send EEPROM address for write */
    I2C_Send7bitAddress(I2C1, EEPROM_ADDRESS, I2C_Direction_Transmitter);
  }while(!(I2C_ReadRegister(I2C1, I2C_Register_SR1) & 0x0002));
 
  /* Clear AF flag */
  I2C_ClearFlag(I2C1, I2C_FLAG_AF);
    /* STOP condition */   
    I2C_GenerateSTOP(I2C1, ENABLE); // Added by Najoua 27/08/2008
}


工程师
2012-06-16 00:11:11     打赏
118楼

TFT驱动起来了,目前没有做汉字的字库,所以还不能显示汉字。将图片贴出来啊,手机照的,TFT上的字符看不清,不过凭字形还是能够看出是我的EEPW ID的,哈哈。还有我的TFT是直立的插在开发板上的,所以感觉有点别扭。另外感谢hanshuyujifen2给我提供了LCD驱动代码啊,我一开始我认为自己的驱动是有问题的,后来发现原来是自己对TFT操作不熟练的原因,自己的驱动也是可以工作的。不过还是感谢hanshuyujifen2啊!
上图:




工程师
2012-06-16 00:28:25     打赏
119楼




这个ucGUI还没有理解透,就又请教了hanshuyujifen2,暂时只能移植到这样了,看来想达到应用还有很长的路要走,这肯定到评分之后了,慢慢来吧。最主要的是学到东西,把别人的东西变成自己的。看来暂时只能更新这些了。如果明后天考完后能够快速恢复网络,可以上网的话,就再接着更新一点吧。得睡觉了,明天考试啊,亲们!


工程师
2012-06-16 00:40:40     打赏
120楼
         STM32内置两个看门狗,提供了更高的安全性、时间的精确性和使用的灵活性。两个看门狗设备(独立看门狗和窗口看门狗)可用来检测和解决由软件错误引起的故障;当计数器达到给定的超时值时,触发一个中断(仅适用于窗口型看门狗)或产生系统复位。 
        独立看门狗(IWDG)由专用的低速时钟(LSI)驱动,即使主时钟发生故障它也仍然有效。窗口看门狗由从APB1时钟分频后得到的时钟驱动,通过可配置的时间窗口来检测应用程序非正常的过迟或过早的操作。 
        IWDG最适合应用于那些需要看门狗作为一个在主程序之外,能够完全独立工作,并且对时间精度要求较低的场合。WWDG最适合那些要求看门狗在精确计时窗口起作用的应用程序。
        在键寄存器(IWDG_KR)中写入0xCCCC,开始启用独立看门狗;此时计数器开始从其复位值0xFFF递减计数。当计数器计数到末尾0x000时,会产生一个复位信号(IWDG_RESET)。 无论何时,只要在键寄存器IWDG_KR中写入0xAAAA, IWDG_RLR中的值就会被重新加载到计数器,从而避免产生看门狗复位 。       
        这个独立看门狗的实验,用起来也是不难的,就是配置好看门狗之后,要按时喂狗,不然系统就会复位。这里参考原子的寄存器方式操作的,程序运行后则开启IWDG,并使得LED3常亮,在主循环里面不停的检测WK_UP按键是否按下,如果有按下,则喂狗,否则等待看门狗复位。看门狗复位可以看到LED3不停的闪烁。
由于实验较简单,而照相片不能较好的演示本实验,视频又挺麻烦的,所以就不上演示效果了。
        现将独立看门狗的配置代码附上:
void IWDG_Init(u8 prer,u16 rlr)
{
 IWDG->KR=0X5555;//使能对IWDG->PR和IWDG->RLR的写              
   IWDG->PR=prer;  //设置分频系数  
   IWDG->RLR=rlr;  //从加载寄存器 IWDG->RLR 
 IWDG->KR=0XAAAA;//reload             
   IWDG->KR=0XCCCC;//使能看门狗 
}
//喂独立看门狗
void IWDG_Feed(void)
{
 IWDG->KR=0XAAAA;//reload             
}

共124条 12/13 |‹ 8 9 10 11 12 13 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]