小肥羊dsf 发表于 2019-11-19 16:48:22

STM32F103 AD 在写完flash后变得不准

STM32F103AD 在写完flash后变得不准经过过测试和不相干IO口设置有关怎么回事
IO口设置代码
void Init_Dev(void)
{

   //Rtc_Init();
   Init_key();
   Init_Set();
   InitLight();
   InitAUX();
   InitFan();
   InitDefrost();
   InitComp();
   BuzzInit();
   GN1621_Dev_Init();
   DS1302_IO_Init();
   Ds1302_Init();
   InitDoor();
   uart_init2(9600);
   uart_init1(9600);
   HotKey_Dispy_Init();
   uart_init3(9600);
   Adc_Init();
   SwitchInit();
   CodeText();
   TIM3_Mode_Config();
   InitAlarm();
   


}
TIM3_Mode_Config();







//配置成PWM输出
void TIM3_Mode_Config(void)
{
   TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;//初始化TIM2的时间基数单位
   TIM_OCInitTypeDefTIM_OCInitStructure;//初始化TIM2的外设
   GPIO_InitTypeDef GPIO_InitStructure;

/*
   关掉JTAD调式 PA15作为普通IO口
*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

//由于PA6是复用的所以要设置一下
//GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE);

//配置PA16 PWM输出的模式
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;               
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

//打开TIM3的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

//TIM2的时间基数单位设置(如计数终止值:999,从0开始 ;计数方式:向上计数)         
#if INSIDE_RCC
   TIM_TimeBaseStructure.TIM_Prescaler= (2 - 1); //时钟预分频数,时钟频率=64MHZ/(时钟预分频+1) 之后是8M   
   TIM_TimeBaseStructure.TIM_Period=3200-1; //自动重装载寄存器的值/10KHZ
#else
   TIM_TimeBaseStructure.TIM_Prescaler= (9 - 1); //时钟预分频数,时钟频率=72MHZ/(时钟预分频+1) 之后是8M   
   TIM_TimeBaseStructure.TIM_Period=1000-1; //自动重装载寄存器的值/        8KHZ
#endif

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;      
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

//TIM3的外设的设置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;      //TIM脉冲宽度调制模式1   
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//这个暂时不知道,stm32固件库里没有搜到。应该是定时器输出声明使能的意思      
TIM_OCInitStructure.TIM_Pulse = 500;//设置了待装入捕获比较寄存器的脉冲值         
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //TIM输出比较极性高
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
         
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能或者失能TIMx在CCR1上的预装载寄存器
TIM_ARRPreloadConfig(TIM3, ENABLE);      //使能TIM2重载寄存器ARR

TIM_ClearFlag(TIM3, TIM_FLAG_Update); //清除溢出中断标志
TIM_Cmd(TIM3, ENABLE);//使能TIM2   


}
InitAlarm();的代码这不是AD IO端口
void InitAlarm(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

        /*
   关掉JTAD调式 PA15作为普通IO口
        */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
        GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
       

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
        GPIO_ResetBits(GPIOB,GPIO_Pin_9);


}
当写完flash后AD值就不对了
测试发现
把void InitAlarm(void)里面的
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
        GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
删除就对了AD的值又对了
或者把
TIM3_Mode_Config();
   InitAlarm();
顺序变了就行了AD的值又对了
或者调试的时候停止然后在重新运行AD值也对
我想应该不是和AD的函数的问题


小肥羊dsf 发表于 2019-11-19 16:49:40

这是AD的代码


void ADC_NVIC_Config(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;        // 优先级分组       
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);   // 配置中断优先级
        NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
}


void Adc_Init(void)
{
        ADC_InitTypeDef ADC_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC |RCC_APB2Periph_ADC1    , ENABLE );       //使能ADC1通道时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC        , ENABLE);

        RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //复用推挽输出
        GPIO_Init(GPIOA, &GPIO_InitStructure);


        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //复用推挽输出
        GPIO_Init(GPIOA, &GPIO_InitStructure);


        //ADC1配置
        //独立工作模式
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
        //扫描方式
        ADC_InitStructure.ADC_ScanConvMode = DISABLE; //不扫描
        //连续转换
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //单次转换
        //外部触发禁止
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;       
        //数据右对齐
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
        //用于转换的通道数
        ADC_InitStructure.ADC_NbrOfChannel = 1;       
        ADC_Init(ADC1, &ADC_InitStructure);       

        //规则模式通道配置
        //ADC_RegularChannelConfig(ADC1, ADC_Channel_10 , 1, ADC_SampleTime_239Cycles5); //扭蛋机的
        //ADC_RegularChannelConfig(ADC1, ADC_Channel_13 , 2, ADC_SampleTime_239Cycles5);
        //ADC_RegularChannelConfig(ADC1, ADC_Channel_12 , 3, ADC_SampleTime_239Cycles5);
        //ADC_RegularChannelConfig(ADC1, ADC_Channel_11 , 4, ADC_SampleTime_239Cycles5);

        //使能ADC1的DMA       
        //ADC_DMACmd(ADC1, ENABLE);


    ADC_NVIC_Config();
        // ADC1 转换结束产生中断,在中断服务程序中读取转换值
        ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);


        //使能ADC1
        ADC_Cmd(ADC1, ENABLE);

        //使能ADC1复位校准寄存器   
        ADC_ResetCalibration(ADC1);       
        //检查校准寄存器是否复位完毕
        while(ADC_GetResetCalibrationStatus(ADC1));       

        //开始校准
        ADC_StartCalibration(ADC1);       
        //检测是否校准完毕
        while(ADC_GetCalibrationStatus(ADC1));

        //开启ADC1的软件转换
        //ADC_SoftwareStartConvCmd(ADC1, ENABLE);       

}




void ADC1_2_IRQHandler(void)
{               
        if (ADC_GetITStatus(ADC1,ADC_IT_EOC)==SET)        
        {   // 读取ADC的转换值               
          ADC_Data = ADC_GetConversionValue(ADC1);
                ADC_FinshFlag=1;
        }       
        ADC_ClearITPendingBit(ADC1,ADC_IT_EOC);
}




void SwitchInit(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

        /*
   关掉JTAD调式 PA15作为普通IO口
        */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
        GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //复用推挽输出
        GPIO_Init(GPIOB, &GPIO_InitStructure);

       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //复用推挽输出
        GPIO_Init(GPIOC, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //复用推挽输出
        GPIO_Init(GPIOC, &GPIO_InitStructure);

        GPIO_ResetBits(GPIOC,GPIO_Pin_4);

}
//选择转换通道
void SiwtchChanl(u8 num)
{

switch(num)
{
        case 0:
      GPIO_ResetBits(GPIOC,GPIO_Pin_5);
                GPIO_SetBits(GPIOB,GPIO_Pin_0);
                break;
        case 1:
                GPIO_SetBits(GPIOC,GPIO_Pin_5);
                GPIO_SetBits(GPIOB,GPIO_Pin_0);
                break;
        case 2:
                GPIO_SetBits(GPIOC,GPIO_Pin_5);
                GPIO_ResetBits(GPIOB,GPIO_Pin_0);
                break;
        case 3:
      GPIO_ResetBits(GPIOC,GPIO_Pin_5);
                GPIO_ResetBits(GPIOB,GPIO_Pin_0);
                break;
    default:break;
}
}


//开始转换
void StartADC(u8 num)
{
    u8 tmp;

        CompRum.tPb=0;
        //SetDisplay.Lod=0;
        //SetDisplay.rES=1;
        tmp=CompRum.tPb;
        if(tmp>0)
        {
             //PT1000
                ADC_RegularChannelConfig(ADC1, ADC_Channel_1 , 1, ADC_SampleTime_239Cycles5);
                GPIO_SetBits(GPIOC,GPIO_Pin_4);
                SiwtchChanl(num);
      os_dly_wait(100);

        }else
        {
             //NTC
                ADC_RegularChannelConfig(ADC1, ADC_Channel_0 , 1, ADC_SampleTime_239Cycles5);
                GPIO_ResetBits(GPIOC,GPIO_Pin_4);
                SiwtchChanl(num);
      os_dly_wait(20);
        }



ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}


u16 GetADCData(void)
{

   u16 dataRe=0;
   dataRe=ADC_Data;
   return dataRe;
}

小肥羊dsf 发表于 2019-11-19 16:52:04

这是flash读写的代码#include "stmflash.h"
//#include "delay.h"
//#include "usart.h"

//////////////////////////////////////////////////////////////////////////////////       
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK miniSTM32开发板
//STM32 FLASH 驱动代码          
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/9/13
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved                                                                          
//////////////////////////////////////////////////////////////////////////////////

//读取指定地址的半字(16位数据)
//faddr:读地址(此地址必须为2的倍数!!)
//返回值:对应数据.
u16 STMFLASH_ReadHalfWord(u32 faddr)
{
        return *(vu16*)faddr;
}
#if STM32_FLASH_WREN        //如果使能了写   
//不检查的写入
//WriteAddr:起始地址
//pBuffer:数据指针
//NumToWrite:半字(16位)数   
void STMFLASH_Write_NoCheck(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)   
{                                       
        u16 i;
        for(i=0;i<NumToWrite;i++)
        {
                FLASH_ProgramHalfWord(WriteAddr,pBuffer);
          WriteAddr+=2;//地址增加2.
        }
}
//从指定地址开始写入指定长度的数据
//WriteAddr:起始地址(此地址必须为2的倍数!!)
//pBuffer:数据指针
//NumToWrite:半字(16位)数(就是要写入的16位数据的个数.)
#if STM32_FLASH_SIZE<256
#define STM_SECTOR_SIZE 1024 //字节
#else
#define STM_SECTOR_SIZE        2048
#endif               
u16 STMFLASH_BUF;//最多是2K字节
void STMFLASH_Write(u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)       
{
        u32 secpos;           //扇区地址
        u16 secoff;           //扇区内偏移地址(16位字计算)
        u16 secremain; //扇区内剩余地址(16位字计算)          
        u16 i;   
        u32 offaddr;   //去掉0X08000000后的地址
        if(WriteAddr<STM32_FLASH_BASE||(WriteAddr>=(STM32_FLASH_BASE+1024*STM32_FLASH_SIZE)))return;//非法地址
        FLASH_Unlock();                                                //解锁
        offaddr=WriteAddr-STM32_FLASH_BASE;                //实际偏移地址.
        secpos=offaddr/STM_SECTOR_SIZE;                        //扇区地址0~127 for STM32F103RBT6
        secoff=(offaddr%STM_SECTOR_SIZE)/2;                //在扇区内的偏移(2个字节为基本单位.)
        secremain=STM_SECTOR_SIZE/2-secoff;                //扇区剩余空间大小   
        if(NumToWrite<=secremain)secremain=NumToWrite;//不大于该扇区范围
        while(1)
        {       
                STMFLASH_Read(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//读出整个扇区的内容
                for(i=0;i<secremain;i++)//校验数据
                {
                        if(STMFLASH_BUF!=0XFFFF)break;//需要擦除          
                }
                if(i<secremain)//需要擦除
                {
                        FLASH_ErasePage(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE);//擦除这个扇区
                        for(i=0;i<secremain;i++)//复制
                        {
                                STMFLASH_BUF=pBuffer;          
                        }
                        STMFLASH_Write_NoCheck(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE,STMFLASH_BUF,STM_SECTOR_SIZE/2);//写入整个扇区
                }else STMFLASH_Write_NoCheck(WriteAddr,pBuffer,secremain);//写已经擦除了的,直接写入扇区剩余区间.                                   
                if(NumToWrite==secremain)break;//写入结束了
                else//写入未结束
                {
                        secpos++;                                //扇区地址增1
                        secoff=0;                                //偏移位置为0        
                           pBuffer+=secremain;        //指针偏移
                        WriteAddr+=secremain;        //写地址偏移          
                           NumToWrite-=secremain;        //字节(16位)数递减
                        if(NumToWrite>(STM_SECTOR_SIZE/2))secremain=STM_SECTOR_SIZE/2;//下一个扇区还是写不完
                        else secremain=NumToWrite;//下一个扇区可以写完了
                }       
        };       
        FLASH_Lock();//上锁
}
#endif

//从指定地址开始读出指定长度的数据
//ReadAddr:起始地址
//pBuffer:数据指针
//NumToWrite:半字(16位)数
void STMFLASH_Read(u32 ReadAddr,u16 *pBuffer,u16 NumToRead)          
{
        u16 i;
        for(i=0;i<NumToRead;i++)
        {
                pBuffer=STMFLASH_ReadHalfWord(ReadAddr);//读取2个字节.
                ReadAddr+=2;//偏移2个字节.       
        }
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
//WriteAddr:起始地址
//WriteData:要写入的数据
void Test_Write(u32 WriteAddr,u16 WriteData)          
{
        STMFLASH_Write(WriteAddr,&WriteData,1);//写入一个字
}


void Erase_Flash(uint32_t WriteAddr)
{
        FLASH_Unlock();
        FLASH_ErasePage(WriteAddr);
        FLASH_Lock();//上锁
}



这是调用flash读写函数
#include "keep.h"


#define   ONE_PAGE 1024

#defineSET_BASE_ADDR      STM32_FLASH_BASE+ONE_PAGE*61//第61页
#defineCompRum_ADDR       SET_BASE_ADDR+100*0
#defineSetProbe_ADDR      SET_BASE_ADDR+100*1
#defineSetDisplay_ADDR    SET_BASE_ADDR+100*2
#defineFrost_Set_ADDR   SET_BASE_ADDR+100*3
#defineFan_ADDR         SET_BASE_ADDR+100*4
#defineDoor_ADDR          SET_BASE_ADDR+100*5
#defineAux_s_ADDR         SET_BASE_ADDR+100*6
#defineAlarm_s_ADDR       SET_BASE_ADDR+100*7
#defineRTC_s_ADDR         SET_BASE_ADDR+100*8



//新机第一次上电的时候清除数据
#define UPDATAFLAG   0x5887
void CreanZore(void)
{
       
        ReadSetData();
        if(PowerUp!=UPDATAFLAG)
        {
                PowerUp=UPDATAFLAG;
                DefalutSys();
                WriteSetData();       
                SetTime.update=1;
        }
}


void ReadSetData(void)
{

        u32 address;
        u16 buf;

        memset(buf,0,100);
        address=CompRum_ADDR;
        STMFLASH_Read(address,buf,50);
        memcpy(&PowerUp,buf,4);
        memcpy(&CompRum,&buf,sizeof(CompRum));
       

        memset(buf,0,100);
        address=SetProbe_ADDR;
        STMFLASH_Read(address,buf,50);
        memcpy(&SetProbe,buf,sizeof(SetProbe));
       

        memset(buf,0,100);
        address=SetDisplay_ADDR;
        STMFLASH_Read(address,buf,50);
        memcpy(&SetDisplay,buf,sizeof(SetDisplay));


        memset(buf,0,100);
        address=Frost_Set_ADDR;
        STMFLASH_Read(address,buf,50);
        memcpy(&Frost_Set,buf,sizeof(Frost_Set));


        memset(buf,0,100);
        address=Fan_ADDR;
        STMFLASH_Read(address,buf,50);
        memcpy(&Fan,buf,sizeof(Fan));


        memset(buf,0,100);
        address=Door_ADDR;
        STMFLASH_Read(address,buf,50);
        memcpy(&Door_s,buf,sizeof(Door_s));


        memset(buf,0,100);
        address=Aux_s_ADDR;
        STMFLASH_Read(address,buf,50);
        memcpy(&Aux_s,buf,sizeof(Aux_s));


        memset(buf,0,100);
        address=Alarm_s_ADDR;
        STMFLASH_Read(address,buf,50);
        memcpy(&Alarm_s,buf,sizeof(Alarm_s));

        memset(buf,0,100);
        address=RTC_s_ADDR;
        STMFLASH_Read(address,buf,50);
        memcpy(&Rtc_Set,buf,sizeof(Rtc_Set));

       
}


void WriteSetData(void)
{

        u32 address;
        u16 buf;

        memset(buf,0,100);
        address=CompRum_ADDR;
        memcpy(buf,&PowerUp,4);
        memcpy(&buf,&CompRum,sizeof(CompRum));
        STMFLASH_Write(address,buf,50);

    memset(buf,0,100);
        address=SetProbe_ADDR;
        memcpy(buf,&SetProbe,sizeof(SetProbe));
        STMFLASH_Write(address,buf,50);

    memset(buf,0,100);
        address=SetDisplay_ADDR;
        memcpy(buf,&SetDisplay,sizeof(SetDisplay));
        STMFLASH_Write(address,buf,50);

        memset(buf,0,100);
        address=Frost_Set_ADDR;
        memcpy(buf,&Frost_Set,sizeof(Frost_Set));
        STMFLASH_Write(address,buf,50);

    memset(buf,0,100);
        address=Fan_ADDR;
        memcpy(buf,&Fan,sizeof(Fan));
        STMFLASH_Write(address,buf,50);

        memset(buf,0,100);
        address=Door_ADDR;
        memcpy(buf,&Door_s,sizeof(Door_s));
        STMFLASH_Write(address,buf,50);

        memset(buf,0,100);
        address=Aux_s_ADDR;
        memcpy(buf,&Aux_s,sizeof(Aux_s));
        STMFLASH_Write(address,buf,50);

        memset(buf,0,100);
        address=Alarm_s_ADDR;
        memcpy(buf,&Alarm_s,sizeof(Alarm_s));
        STMFLASH_Write(address,buf,50);

        memset(buf,0,100);
        address=RTC_s_ADDR;
        memcpy(buf,&Rtc_Set,sizeof(Rtc_Set));
        STMFLASH_Write(address,buf,50);

}

void UapdateProc(void)
{

   if(UpdateFlag>0)
   {
      UpdateFlag=0;
      WriteSetData();
          Buzzer_Cnt=3;
   }
}

小肥羊dsf 发表于 2019-11-19 16:52:31

#include "keep.h"

小肥羊dsf 发表于 2019-11-19 16:53:15

Flash读写函数#include "stmflash.h"
/

小肥羊dsf 发表于 2019-11-19 16:53:50

#include "stmflash.h"

小肥羊dsf 发表于 2019-11-19 16:56:17

系统延时发多了

小肥羊dsf 发表于 2019-11-20 13:31:56

自己给自己顶

小肥羊dsf 发表于 2019-12-9 11:41:45

:(:'(:Q:Q:Q:Q:Q:Q

butterflyspring 发表于 2019-12-10 10:05:19

试试对比一下前后AD相关的配置寄存器内容是否有变化,包括时钟配置,IO配置的内容。如有变化可以顺着线索找找哪里逻辑需要补充:)
页: [1] 2
查看完整版本: STM32F103 AD 在写完flash后变得不准