詳しい話は、また別の機会に。
とりあえず、ポートの制限がなくなった。
さて本題。情報としては知っていたのだけれど、STM32のAD変換で、はまった。
STM32の12bitAD変換は変換結果を左詰にするか、右詰にするかを選べるのだけれど、右詰に設定しても、それが有効化されないのだ。
花岡ちゃんに花束を(STM32F4のAD変換トラブル(その2))
このページで、ADCの初期化でADC_DeInit();を実行すれば良いとされているが、それだけでは解決されなかった。
試行錯誤の結果、ADCの初期化処理の最後にウェイト処理を追加することで解決したので、ADCの初期化が完了する前に、ADCを使い始めてしまったのだろうか?
おそらく、データシートには書いてあるのだろうけれど、詳しく見てないので分からない。
ソースコードは以下。
#include "stm32f4xx.h"
#include "uart1.h"
#include "stm32f4dis.h"
/* --------------------------------------
time : 約1uSec,1000000=1sec
-------------------------------------- */
void delay(uint32_t time){
uint32_t t;
volatile uint8_t i;
for(i=0;i<24;i++){
t = time;
while(t--);
}
}
// -------------------------------------------------------------------
// systick 割込み(1msec毎に設定してある)
// stm32f4xx_it.c で呼び出している
// -------------------------------------------------------------------
volatile uint16_t time_sec=0;
volatile uint16_t time_msec=0;
void systick_1msec(void){
static uint16_t cnt=0;
cnt++;
time_msec++;
if(cnt>1000){
time_msec=0;
cnt=0;
time_sec++;
}
}
void Delay_ms(uint16_t msec){
uint16_t cnt=0;
cnt = time_msec;
while(msec){
if(cnt!=time_msec){
cnt = time_msec;
msec--;
}
}
}
// -------------------------------------------------------------------
// ADC3 初期化
// -------------------------------------------------------------------
void adc3_init(void){
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//必要なペリフェラルにクロック供給開始
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
//GPIO-Cの指定の入力をアナログに設定
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; //PC[13:10]をアナログ入力に設定
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOC, &GPIO_InitStructure);
ADC_DeInit(); // AD変換器のリセット
//ADC3の変換モード設定。
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
// ↓ ENABLE(スキャンモード)、DISABLE(分割スキャンモード)
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
// ↓ ENABLE(連続変換モード)、DISABLE(シングル変換モード)
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
// ↓ AD変換開始トリガなし
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
// ↓ AD変換後のデータ右詰
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
// ↓ 入力を4本(チャネルを増やしたらここを変える)
ADC_InitStructure.ADC_NbrOfConversion = 4;
ADC_Init(ADC3, &ADC_InitStructure);
ADC_Cmd(ADC3, ENABLE); // ADC3を有効化
delay(10000); // 大切!
}
// -------------------------------------------------------
//
// -------------------------------------------------------
int main(void)
{
volatile uint16_t time_tmp=0;
uint16_t adc1_data=0; // ADC変換後のデータを格納
uint16_t adc2_data=0; // ADC変換後のデータを格納
uint16_t adc3_data=0; // ADC変換後のデータを格納
uint16_t adc4_data=0; // ADC変換後のデータを格納
SystemInit();
stm32f4_init(); set_led(0x01);
delay(10000);
adc3_init(); set_led(0x02);
uart1_init(9600);
usart1_printf(\"\\r\\n\");
usart1_printf(\"micro mouse ver0.0.1\\r\\n\");
// systick 設定(1msec)
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
if(SysTick_Config(SystemCoreClock/1000)){
while(1); // error
}
while(1){
// SW処理
if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13)){
//ボタンが押されて1になっていたら以下を実行
GPIO_ResetBits(GPIOB,GPIO_Pin_7); // 点灯
while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13)); // ボタンを放したら以下を実行
}else{
GPIO_SetBits(GPIOB,GPIO_Pin_7); // 消灯
}
// 1秒処理
if(time_tmp!=time_sec){
set_led(0x04);
time_tmp = time_sec;
ADC_RegularChannelConfig( ADC3, ADC_Channel_10, 1, ADC_SampleTime_56Cycles);
ADC_SoftwareStartConv( ADC3 ); // AD変換開始
while(ADC_GetFlagStatus(ADC3,ADC_FLAG_EOC) == RESET);
adc1_data = ADC_GetConversionValue(ADC3); // AD変換データの取り込み
adc1_data = adc1_data *3300/0xFFF; // 電圧に変換
ADC_RegularChannelConfig( ADC3, ADC_Channel_11, 1, ADC_SampleTime_56Cycles);
ADC_SoftwareStartConv( ADC3 ); // AD変換開始
while(ADC_GetFlagStatus(ADC3,ADC_FLAG_EOC) == RESET);
adc2_data = ADC_GetConversionValue(ADC3); // AD変換データの取り込み
// adc2_data = adc2_data *3300/0xFFF; // 電圧に変換
ADC_RegularChannelConfig( ADC3, ADC_Channel_12, 1, ADC_SampleTime_56Cycles);
ADC_SoftwareStartConv( ADC3 ); // AD変換開始
while(ADC_GetFlagStatus(ADC3,ADC_FLAG_EOC) == RESET);
adc3_data = ADC_GetConversionValue(ADC3); // AD変換データの取り込み
adc3_data = adc3_data *3300/0xFFF; // 電圧に変換
ADC_RegularChannelConfig( ADC3, ADC_Channel_13, 1, ADC_SampleTime_56Cycles);
ADC_SoftwareStartConv( ADC3 ); // AD変換開始
while(ADC_GetFlagStatus(ADC3,ADC_FLAG_EOC) == RESET);
adc4_data = ADC_GetConversionValue(ADC3); // AD変換データの取り込み
adc4_data = adc4_data *3300/0xFFF; // 電圧に変換
usart1_printf(\"%4d : AD ch1=%4d , ch2=0x%8X , ch3=%4d , ch4=%4d \\r\",
time_sec,adc1_data,adc2_data,adc3_data,adc4_data);
set_led(0x00);
}
}
return 0;
}
0 件のコメント:
コメントを投稿