COKPOWEHEU

stm32f103 и компас GY-271

15 сообщений в этой теме

COKPOWEHEU    265

Решил разобраться с модулем компаса GY-271 - одним из немногих модулей, которые вообще сумел найти. Пол-интернета заполнены утверждениями что собран данный модуль на микросхеме HMC5883L, которая общается по I2C и отзывается на адрес 0x1E (соответственно, 0x3C/0x3D для записи и чтения). На практике же посылка этого адреса натыкалась на глухой таймаут, мол знать не знаем такого адреса, и вообще мы не оно. Целенаправленные, но больше случайные поиски по интернету дали наводку что данное чудо техники, возможно, отзовется на адрес 0x0D (0x1A/0x1B для записи и чтения) и действительно, по такому адресу удалось добиться ответа, правда не совсем того, что ожидалось. К примеру, без "шаманской" (опять же, советы из "Всезнающего") записи единицы по адресу 9, ответ был нулевым. Потом более-менее осмысленные данные появились, но не с адреса 0x03, как положено по даташиту, а вовсе даже с 0x00. Очередная случайная находка дала направление, что заботливые китайцы запаяли на плату не HMC5883L, а вовсе даже QMC5883L - совсем другую микросхему с другими регистрами. И вот она действительно похожа по настройкам и адресу.

Стал бы я создавать тему, если бы все было так хорошо... Хотя ответ от микросхемы и есть, как-то он слабо похож на нормальные данные. Теоретически, в регистрах 1:0, 3:2, 5:4 должны быть проекции магнитного поля на оси X, Y, Z. То есть вдали от магнитов и массивных железяк, геометрическая сумма значений должны быть примерно 0.5 Гс, то есть ~32000 единиц модуля, причем пока модуль лежит на столе, сильно меняться значениям не с чего. Привожу лог снятых данных (во вложении исходный код прошивки: вся работа с периферией идет руками, без автоконфигураторов и тому подобного). За все время съема этого лога модель лежал на столе в одном положении, но данные по осям скачут достаточно произвольным образом.

I2C test
FB FF 0A 00 14 00 00 A8 F5 0D 00 01 01 00 Write
0F 00 05 00 F1 FF 04 99 F5 | 15 5 -15 2337
FB FF 00 00 05 00 00 9A F5 | -5 0 5 2338
0F 00 05 00 00 00 00 8F F5 | 15 5 0 2327
E2 FF 00 00 F6 FF 00 93 F5 | -30 0 -10 2331
28 00 F6 FF FB FF 00 90 F5 | 40 -10 -5 2328
05 00 FB FF FB FF 00 99 F5 | 5 -5 -5 2337
00 00 00 00 00 00 00 97 F5 | 0 0 0 2335
00 00 0F 00 D6 FF 00 99 F5 | 0 15 -42 2337
32 00 E2 FF 00 00 00 94 F5 | 50 -30 0 2332
E7 FF EC FF 00 00 00 97 F5 | -25 -20 0 2335
05 00 F6 FF 00 00 04 92 F5 | 5 -10 0 2330

Продублирую код чтения регистра (насколько я знаю, он довольно типичный, но мало ли...). Естественно, код писался в первую очередь под конкретную задачу - оптимизация будет потом, если оно вообще заработает.

void I2C_Read(uint8_t device, uint8_t addr, uint8_t *buf, uint8_t count){
  //start
  I2C2->CR1 |= I2C_CR1_START;
  while(!(I2C2->SR1 & I2C_SR1_SB)){}
  (void) I2C2->SR1;
 
  //device
  I2C2->DR = (device<<1) &~(1<<0);
  while(!(I2C2->SR1 & I2C_SR1_ADDR)){}
  (void) I2C2->SR1;
  (void) I2C2->SR2;
 
  //addr
  I2C2->DR = addr;
  while(!(I2C2->SR1 & I2C_SR1_TXE)){}
  I2C2->CR1 |= I2C_CR1_STOP;
 
  //restart
  I2C2->CR1 |= I2C_CR1_START;
  while(!(I2C2->SR1 & I2C_SR1_SB)){}
 
  //device
  I2C2->DR = (device<<1) | (1<<0);
  while(!(I2C2->SR1 & I2C_SR1_ADDR)){}
  (void) I2C2->SR1;
  (void) I2C2->SR2;
 
  //data
  for(uint8_t i=0; i<count-1; i++){
    //I2C2->CR1 &=~ I2C_CR1_ACK;
    I2C2->CR1 |= I2C_CR1_ACK;
    while(!(I2C2->SR1 & I2C_SR1_RXNE)){}
    buf[i] = I2C2->DR;
  }
  I2C2->CR1 &=~I2C_CR1_ACK;
  while(!(I2C2->SR1 & I2C_SR1_RXNE)){}
  buf[count-1] = I2C2->DR;
 
  //stop
  I2C2->CR1 |= I2C_CR1_STOP;
}
#define QMC5883L 0x0D

  I2C_Read(QMC5883L, 0, data, 14);
  for(uint8_t i=0; i<14; i++){
    UART_HEX(data[i]); UART_putc(USART, ' ');
  }

  data[0] = 0x80;
  I2C_Write(QMC5883L, 10, data, 1);
  data[0] = 0x01;
  I2C_Write(QMC5883L, 0x0B, data, 1);

 
  data[0] = (0b00<<6) | (0b00<<4) | (0b11<<2) | (0b01<<0);
  //oversampling = 512
  //range = 2 G
  //ODR = 200 Hz
  //mode = continuous
  I2C_Write(QMC5883L, 9, data, 1);

  UART_puts(USART, "Write\x0d\n");

  while(1){
    I2C_Read(QMC5883L, 0, data, 9);
    for(uint8_t i=0; i<9; i++){
      UART_HEX(data[i]); UART_putc(USART, ' ');
    }
    i16a x,y,z,t;
    x.u8val[0] = data[0]; x.u8val[1] = data[1];
    y.u8val[0] = data[2]; y.u8val[1] = data[3];
    z.u8val[0] = data[4]; z.u8val[1] = data[5];
    t.u8val[0] = data[7]; t.u8val[1] = data[8];
    t.ival += 3000+2000;
    sprintf(str,"| %i %i %i %i", x.ival, y.ival, z.ival, t.ival);
    UART_puts(USART, str);

Собственно, вопрос: что я делаю не так и как сделать так, чтобы модуль отдавал правильные данные магнитного поля?

compass.rar

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Там проблема с сохранением результатов измерений, если не успеть забрать - портятся. Есть два варианта: Читать статус в режиме нонстоп , и быть привязанным к тактовому генератору компаса (там +- лапоть).  Или запускать однократное измерение по таймеру мк (событие - чтение значений - новый запуск).

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
COKPOWEHEU    265

Добавил ожидание флага DRDY (сначала он возникает вместе с флагом DOR), считываю регистры, потом снова дожидаюсь бита DRDY:

  while(1){
...
    do{
      I2C_Read(QMC5883L, 6, &data[6], 1);
    }while(!(data[6] & 1));
    UART_HEX(data[6]); UART_putc(USART, ' ');
    I2C_Read(QMC5883L, 0, data, 6);
    UART_HEX(data[0]); UART_putc(USART, ' ');
    
    do{
      I2C_Read(QMC5883L, 6, &data[6], 1);
    }while(!(data[6] & 1));
    UART_HEX(data[6]); UART_putc(USART, ' ');

    I2C_Read(QMC5883L, 0, &data[1], 6);
...
  }

Особой разницы нет:

05 00 01 00 05 00 14 00 F1 FF 00 F5 | 1280 5120 -3840 2184
05 BD 01 BD DD FF 00 00 FB FF 00 F5 | -8771 255 -1280 2184
05 14 01 14 23 00 0F 00 1E 00 00 F5 | 8980 3840 7680 2184
05 00 01 00 F6 FF 0F 00 F6 FF 00 F5 | -2560 4095 -2560 2184
05 00 01 00 00 00 00 00 D1 FF 00 F5 | 0 0 -12032 2184
05 14 01 14 DD FF 2D 00 1E 00 00 F5 | -8940 11775 7680 2184

здесь первый байт - считанный регистр 0x06 с битами DRDY+DOR, потом 0-й регистр (считываются-то все, но отображается только он), потом еще раз 6-й регистр (теперь видно, что выставлен только бит DRDY, то есть данные вроде как готовы). Потом считываю данные, но модуль опять выдает непонятно что.

Если запускать одиночные преобразования - как это делать? В даташите алгоритма или подходящих регистров не нашел.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Впервые на русском языке! Работаем с микроконтроллерами STM32F7(на основе STM32F7 Online Training)

Цикл материалов на основе STM32F7 Online Training от компании STMicroelectronics. Описаны функциональные блоки и инструменты разработки для семейства микроконтроллеров STM32F7, охватывающие тематику системной периферии, памяти, безопасности, аналоговой периферии, цифровой периферии, таймеров, экосистемы.

Подробнее>>

Я кажется спутал QMC5883L с другим датчиком, у которого был одиночный режим. Сейчас покопался в своём бардаке, оказывается я его нагло сбрасывал на перемагничивание (калибровку) , и читал по внешнему таймеру. Кстати, у этого датчика есть неприятный глюк - он помнит магнитное поле если оно превышало определённый порог. То-есть если поднести магнитик - то значения магнитного поля не спадают.  Мягкий сброс очищает эту память. 

У датчика на макетке из китая есть стаб 3,3в, он полезен когда внешнее питание 5в. Но при питании от 3,3в - на стабе будут пульсации. Резисторы которые стоят на шине - мне китайцы поставили по 100к, перепаял на 1к.

Ну и самое простое, когда датчик используется на собственной ПП: под ним должен быть массивный полигон, чем больше -тем лучше. Не, датчик не греется, но зато идеально ловит 50герц наводку от сети. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
COKPOWEHEU    265
6 часов назад, AVI-crak Home сказал:

Мягкий сброс очищает эту память. 

мягкий сброс у меня есть, перед бесконечным циклом. Но это ни на что не влияет, даже на первое измерение.

6 часов назад, AVI-crak Home сказал:

У датчика на макетке из китая есть стаб 3,3в, он полезен когда внешнее питание 5в. Но при питании от 3,3в - на стабе будут пульсации. Резисторы которые стоят на шине - мне китайцы поставили по 100к, перепаял на 1к.

То есть советуете запитать сам модуль от 5 В и проверить резисторы подтяжки? Попробую, хотя раз проблем с обменом нет, вряд ли дело в резисторах.

6 часов назад, AVI-crak Home сказал:

Ну и самое простое, когда датчик используется на собственной ПП:

Нет, используется готовый модуль GY-271. Перепаивать буду если заработает, но пока до этого далеко :) В любом случае спасибо за предупреждение.

6 часов назад, AVI-crak Home сказал:

Сейчас покопался в своём бардаке, оказывается я его нагло сбрасывал на перемагничивание (калибровку) , и читал по внешнему таймеру.

Может, поделитесь кодом?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
COKPOWEHEU    265

Проверил резисторы. Оказалось 2.2к. Вроде нормальные. Попробовал подать на модуль пятивольтовое питание - без изменений.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Скрытый текст

    i2xdata.data[0] = 0x00; /// adres_reg - 1
    i2xdata.read_write = 1;
    i2xdata.nBytes = 1;
    i2c_RW_master();



    i2xdata.read_write = 0;
    i2xdata.nBytes = 9;
    i2xdata.read_write = 0;
    i2c_RW_master();


    i2xdata.Sdata[0] = i2xdata.data[0];
    i2xdata.Sdata[0] |= i2xdata.data[1] <<8;
 //   i2xdata.Sdata[0] += 998;

    i2xdata.Sdata[1] = i2xdata.data[2];
    i2xdata.Sdata[1] |= i2xdata.data[3] <<8;
 //   i2xdata.Sdata[1] += 63;

    i2xdata.Sdata[2] = i2xdata.data[4];
    i2xdata.Sdata[2] |= i2xdata.data[5] <<8;
  //  i2xdata.Sdata[2] -= 40;

    i2xdata.Sdata[3] = i2xdata.data[7];
    i2xdata.Sdata[3] |= i2xdata.data[8] << 8;

 

Проблема в том что HMC5883L был первым датчиком что я хотел подружить с stm. Непонимание того как работает протокол шины и аппаратная часть мк - дало очень забавного уродца. Массив i2xdata.data - это то что я записывал или читал из чипа.

Запуск чипа делался до победного конца, пока его не отпустит. Для HMC5883L есть режим залипания, когда он позволяет только читать свои регистры, и больше ни на что не реагирует. То-есть в случае сброса всей системы - вполне возможно получить ситуацию когда данные прочитались частично, а датчик не имеет аппаратного сброса.

Скрытый текст

volatile struct _i2xdata
{
    uint8_t adres_mx;
    uint8_t nBytes;
    uint8_t read_write; ///0-1
    uint8_t status;
    uint8_t data[10];
    int16_t Sdata[4];
    float Sdata2[4];
}i2xdata;
----------------
    i2xdata.adres_mx = 0x0d;

  do
  {
    i2xdata.status = 0;

    i2xdata.adres_mx = 0x0d;
    i2xdata.data[0] = 0x0a;
    i2xdata.data[1] = 0x80;
    i2xdata.read_write = 1;
    i2xdata.nBytes = 2;
    i2c_RW_master();
    sDelay_mc(50);

    i2xdata.data[0] = 0x0B; /// adres_reg - 1
    i2xdata.data[1] = 1; ///  demagnetization
    i2xdata.read_write = 1;
    i2xdata.nBytes = 2;
    i2c_RW_master();
    sDelay_mc(10);

    i2xdata.data[0] = 0x09; /// adres_reg - 1
    i2xdata.data[1] = 0x1;
    i2xdata.read_write = 1;
    i2xdata.nBytes = 2;
    i2c_RW_master();
  } while (i2xdata.status);

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
COKPOWEHEU    265

@AVI-crak Home , спасибо, код посмотрел, но вряд ли поможет.

HappyEnd:

Раздобыл Ардуину и нашел несколько разных скетчей для нее (с I2C под stm32 работаю впервые, все же мог накосячить). Даже прогрел строительным феном (вдруг какой контакт не пропаялся). Ничего не меняется: коннект прекрасный, I2C работает замечательно, даже температура считывается, а вот вместо магнитного поля рандомное дерганье.

Значит, скорее всего, просто датчик бракованный попался. Тут ничего не поделаешь, буду искать другой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
ARV    561

Может, на него окружающие магнитные поля действуют?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
COKPOWEHEU    265

Кусок лога данных я выкладывал, все время измерения модуль просто лежал на столе, без движения. Даже если мусорное магнитное поле есть, оно должно складываться с полем Земли, то есть должно быть колебание в районе 8000, а вовсе не +/- 50. Поднесение магнита и повороты датчика тоже не дают видимого эффекта

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В запись цикле:

адрес 0x0d, регистр назначения 0x0a, данные 0x80, ждём 10-50мс.

адрес 0x0d, регистр назначения 0x0B, данные 0x01, ждём 10-50мс.

адрес 0x0d, регистр назначения 0x09, данные 0x01.

До тех пор пока его не отпустит. Датчик очень чувствительно реагирует на паузы между командами, по этому лишнего кода там быть не должно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
COKPOWEHEU    265

Мой код в первом посте, все это я делал. Запись в 0x0B даже уменьшает разброс "показаний". Хуже всего что чужой код дает ровно те же результаты, хотя там народ отписывался что "работает прекрасно". Да и по моему коду видно, что проблемы с I2C нет, микросхема отвечает, на запись в регистры реагирует, даже выдает что-то, что считает данными.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

В том и есть весь прикол, что заставить адекватно реагировать QMC5883L - достаточно трудно. Это не память, которую можно читать вдоль и поперёк, это отдельный процессор с программным I2C. На обращения к регистрам есть небольшие окна - в которые нужно попасть. А потом он начнёт оцифровывать датчики, и в этот момент его трогать нельзя, иначе получится каша.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
COKPOWEHEU    265

@AVI-crak Home еще раз: я дожидаюсь, когда взведется флаг, никакой разницы нет.  Я проверял на готовом коде и готовом железе, где, по уверениям народа, это работает. Более того, народ хвалит датчик, говорит что он менее шумящий, чем HMC5883.

И я прекрасно знаю, как выглядят подобные обвинения "компилятор виноват, контроллер неисправен" когда на самом деле у автора руки кривые. И именно ради этого я искал Ардуину и готовые чужие скетчи, да и по косвенным признакам не вижу других объяснений. Лучшей проверкой было бы найти другой модуль или микросхему (уж развести под него плату не проблема) и проверить на нем, но у меня его под рукой нет. Хотя если в Москве, а лучше в Щелково или рядом, найдется человек, готовый одолжить аналогичный модуль на пару минут, можно проверить и так.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ваша публикация должна быть проверена модератором

Гость
Вы не авторизованы. Если у вас есть аккаунт, пожалуйста, войдите.
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Восстановить форматирование

  Разрешено не более 75 смайлов.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

Загрузка...

  • Похожие публикации

    • Автор: Prominence
      Здравствуйте, в силу поставленных передо мной ограничений (на плате нет внешнего резонатора), я вынужден пытаться запустить STM32F103 от внутреннего тактирования, да ещё и под 72МГц.
      Правильный ли код?
          RCC_DeInit();  //Сброс
          RCC_HSEConfig(RCC_HSE_OFF); //Выключение внешнего тактирования (на всякий случай)
          RCC_PLLConfig( RCC_PLLSource_HSI_Div1, RCC_PLLMul_9); //использование множителя 9 для получения 72МГц, но компилятор ругается на делитель Div1
      Дескать, минимум можно использовать Div2, а совсем без делителя нельзя, как ещё можно выставить множитель?

          RCC_PLLCmd( ENABLE); //Включение PLL как такового
          RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK); //Использование PLL в качестве основного источника тактирования
      Вышеперечисленная шняга будет вызываться в мэйне, но это совсем другая история, пока что с этим туплю.
    • Автор: artos5
      День добрый! Кто работал с такой памятью?? Проблема у меня следующая:
      Считывать массив получается , но иногда он считывается как ноли.
      Писать весь массив (больше одной страницы) тоже не получается, записывается в лучшем случае 2 страницы (64байта) остальной массив остается со старыми данными.
      Но вот если писать страницы по отдельности. Например записать во вторую страницу что то , или в третью и т.д. - то все нормально .
      Как я пишу:
      1) отправляю команду на откл.защиты от записи
      2) отправляю команду что я хочу записать по адресу 0
      3) потом пишу 32 байта 
      далее идет задержка (пробовал разные) 50мс.
      повторяю снова 1,2,3 пункты только адрес уже 32. 
      и снова заливаю 32 байта , CS при зтом поднимаю перед первым пунктом после первого и после третьего пункта.
      Код покажу чуть позже , а то он дома остался....
      Кто работал с этой памятью , что я упустил??? 
       
    • Гость Вячеслав
      Автор: Гость Вячеслав
      Всем привет!
      Есть необходимость выполнять некоторую функцию по таймеру, для этого вызов функции осуществляется по условию и из бесконечного цикла main, выполнение условия - по флагу, собственно, флаг передергивается в обработчике прерывания по таймеру. Проблема заключается в том, что 
      while (1) { if(flag == 1) // сюда программа попадает один раз, последующие передергивания флага дают результат условия 1, однако код в условии не выполняется // дальше цикл бесконечно крутит, таймер дергает флаг, условие сравнивает, но не пускает { func(); flag = 0; } } Контроллер stm32f103c8.
      Буду благодарен и постараюсь оперативно уточнять, если вдруг проблема не типовая и нужно более подробное описание!
    • Автор: kiv.apple
      Пытаюсь разобраться с USB у STM32F103 на низком уровне (т.е. без сторонних библиотек) и столкнулся с проблемой.
      Мои действия:
      1) У меня внешний кварц на 8 МГц. Запускаю PLL на 72 МГц (коэффициент умножения 9, делитель для USB 3). Разумеется, этот процесс состоит из нескольких этапов, однако в результате в регистре RCC->CFGR оказывается значение 0x001DC40A (что помимо прочего обозначает, что PLL успешно выбран как системный источник частоты). Работа USART и SysTick адекватна (частота точно верная).
      2) Включаю тактирование USB. Убираю бит PWDN из USB->CNTR. Жду 1 микросекунду (по даташиту нужно для стабилизации источника опорного напряжения), пишу нули в CNTR, BTABLE и ISTR. Разрешаю прерывания USB_FS_WKUP и CAN1_RX0. Пишу в CNTR значение USB_CNTR_RESETM | USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_CTRM.
      3) На этом инициализация окончена. Далее приходит прерывание от USB. Причина, определённая из ISTR - RESET. Да, именно это и должно случиться, всё логично. Обнуляю соответствующий флаг прерывания.
      4) Настраиваю нулевую конечную точку. В итоге в USB->EP0R оказывается значение 0x3220. По адресу USB_PMA_BASE + 0 оказывается значение 64 (TXADDR для EP0 == 64), по адресу USB_PMA_BASE + 8 оказывается значение 128 (RXADDR для EP0 == 128), по адресу USB_PMA_BASE + 12 оказывается значение 0x8400 (размер буфера приёма для EP0 - 64 байта).
      5) Разрешаю работу USB - пишу в USB->DADDR значение 0x80.
      6) Выхожу из прерывания.
      7) Ожидаю, что мне придёт первый SETUP-пакет, о чём мне скажет прерывание с флагом CTR в регистре ISTR. А оно не приходит. Зато приходит куча прерываний по причине WKUP (я сбрасываю этот флаг, а оно снова приходит). Иногда приходит RESET (у хоста срабатывает таймаут назначения адреса устройству и он устраивает новый сброс), но после него опять куча WKUP. В конце-концов хост забивает на устройство и события прекращаются. Помимо WKUP ещё приходит ESOF.
      Моя теория: USB-модуль не запускается должным образом и не способен разобрать, что приходит по шине кроме RESET. Передача данных видится им как событие WKUP (которое по сути вызывается любой активностью на линии).
      Возможно, я забыл что-то инициализировать или же я что-то неправильно настроил и машину состояний USB клинит.
      В чём может быть проблема? Аппаратная часть исправна - прошивки с использованием готовых библиотек на этой плате работают нормально.
    • Автор: Antidriver
      Доброе время суток.
      Имеется микроконтроллер STM32F103VBT6, на нём заведен ADC1 и используются 6 входных каналов на ножках PA0..PA5. Если в конфигурации установить оцифровку сигнала с пина PA0, то оцифровка проходит успешно, то же самое с пином PA1.
      Ситуация меняется, если пытаюсь оцифровать PA2..PA5. Считываются нули. Ниже привожу код. Просьба подсказать в чём может быть дело и как это исправить.
      Канал меняю в строчке ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_1Cycles5);. К примеру, ADC_Channel_2.

      #include "stm32f10x_rcc.h" #include "stm32f10x_adc.h" #include "stm32f10x_gpio.h" #include "stm32f10x_usart.h" #include "misc.h" #include "delay.h" void SetupUSART(void); void send_to_uart(uint8_t data); void ADC1_2_IRQHandler(void); void Get_Temp(void); uint8_t ind1_B; uint8_t ind2_B; uint8_t ind3_B; uint8_t ind4_B; uint8_t ind5_B; uint8_t ind1_C; uint8_t ind2_C; uint8_t ind3_C; uint8_t ind4_C; uint8_t ind5_C; uint8_t ind1_D; uint8_t ind2_D; uint8_t ind3_D; uint8_t ind4_D; uint8_t ind5_D; uint8_t ind_B; static volatile uint16_t temp=0; int main(void) { SysTick_Config(8000); RCC_APB2PeriphClockCmd(RCC_APB2ENR_AFIOEN, ENABLE); // ?? GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST, ENABLE); //GPIO_PinRemapConfig(GPIO_Remap_USART2, DISABLE); //RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;// ?? //AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_JTAGDISABLE; // ?? disable JTAG GPIO_InitTypeDef GPIO_InitStructure; // PORTA // input RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = /*GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 |*/ GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); // alternative GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); // PORTB // input RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_8; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB, &GPIO_InitStructure); // output GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_4 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); // PORTC // input RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOC, &GPIO_InitStructure); // output GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_13; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOC, &GPIO_InitStructure); // PORTD // input RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOD, &GPIO_InitStructure); // alternative GPIO_InitStructure.GPIO_Pin = (GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); // PWM output pins GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOD, &GPIO_InitStructure); // PORTE // input RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOE, &GPIO_InitStructure); // output GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOE, &GPIO_InitStructure); SetupUSART(); // TIM4 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); // Clock to PORTD for TIM4 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); // Clock to TIM4 GPIO_PinRemapConfig(GPIO_Remap_TIM4, ENABLE); TIM4->CCER |= (TIM_CCER_CC1E|TIM_CCER_CC2E|TIM_CCER_CC3E|TIM_CCER_CC4E); // Enable all PWM outputs TIM4->CCMR1|= (TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2); //Forward PWM for ch1 TIM4 TIM4->CCMR1|= (TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2); //Forward PWM for ch2 TIM4 TIM4->CCMR2|= (TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2); //Forward PWM for ch3 TIM4 TIM4->CCMR2|= (TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2); //Forward PWM for ch4 TIM4 TIM4->CR1 |= TIM_CR1_CEN; TIM4->CCR1 = 65536/5; // Duty cycle PWM1 (Avr voltage = 1.65 V) TIM4->CCR2 = 65536/4; // Duty cycle PWM2 TIM4->CCR3 = 65536/3; // Duty cycle PWM3 TIM4->CCR4 = 65536/2; // Duty cycle PWM4 // ADC RCC_ADCCLKConfig(RCC_PCLK2_Div8); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; ADC_DeInit(ADC1); ADC_InitTypeDef ADC_InitStructure; 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_ITConfig(ADC1, ADC_IT_EOC, ENABLE); NVIC_Init(&NVIC_InitStructure); ADC_Cmd(ADC1, ENABLE); //ADC_TempSensorVrefintCmd(ENABLE); ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1)) { }; ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1)) { }; GPIO_SetBits(GPIOE,GPIO_Pin_1); while(1) { GPIO_SetBits(GPIOC,GPIO_Pin_6); //uint8_t pa2 = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2); //send_to_uart(pa2); //GPIO_SetBits(GPIOB,GPIO_Pin_4); // always 1 /*/chB GPIO_SetBits(GPIOB,GPIO_Pin_6); GPIO_SetBits(GPIOB,GPIO_Pin_4); GPIO_SetBits(GPIOB,GPIO_Pin_7); GPIO_SetBits(GPIOB,GPIO_Pin_9); GPIO_SetBits(GPIOE,GPIO_Pin_0); */ Delay_ms(500); GPIO_ResetBits(GPIOC,GPIO_Pin_6); //GPIO_ResetBits(GPIOB,GPIO_Pin_4); // always 1 /*/chB GPIO_ResetBits(GPIOB,GPIO_Pin_6); GPIO_ResetBits(GPIOB,GPIO_Pin_4); GPIO_ResetBits(GPIOB,GPIO_Pin_7); GPIO_ResetBits(GPIOB,GPIO_Pin_9); GPIO_ResetBits(GPIOE,GPIO_Pin_0); */ Delay_ms(500); ind1_B = GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_6); // ok ind2_B = GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_7); // ok ind3_B = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_3); // ok //(?) always 0 ind4_B = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5); // ok ind5_B = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8); // ok ind1_C = GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2); // ok ind2_C = GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3); // ok ind3_C = GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4); // ok ind4_C = GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_6); // ok ind5_C = GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_1); // ok ind1_D = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6); // ok ind2_D = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7); // ok ind3_D = GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_4); // ok ind4_D = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0); // ok ind5_D = GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_7); // ok //send_to_uart(ind1_; //send_to_uart(ind2_; //send_to_uart(ind3_; //send_to_uart(ind4_; //send_to_uart(ind5_; ind_B = 5-(ind1_B+ind2_B+ind3_B+ind4_B+ind5_; switch (ind_ { case 0: GPIO_ResetBits(GPIOB,GPIO_Pin_6); // sel1_B GPIO_ResetBits(GPIOB,GPIO_Pin_4); // sel2_B GPIO_ResetBits(GPIOB,GPIO_Pin_7); // sel3_B GPIO_ResetBits(GPIOB,GPIO_Pin_9); // sel4_B GPIO_ResetBits(GPIOE,GPIO_Pin_0); // sel5_B break; case 1: GPIO_SetBits(GPIOB,GPIO_Pin_6); // sel1_B GPIO_ResetBits(GPIOB,GPIO_Pin_4); // sel2_B GPIO_ResetBits(GPIOB,GPIO_Pin_7); // sel3_B GPIO_ResetBits(GPIOB,GPIO_Pin_9); // sel4_B GPIO_ResetBits(GPIOE,GPIO_Pin_0); // sel5_B break; case 2: GPIO_ResetBits(GPIOB,GPIO_Pin_6); // sel1_B GPIO_SetBits(GPIOB,GPIO_Pin_4); // sel2_B GPIO_ResetBits(GPIOB,GPIO_Pin_7); // sel3_B GPIO_ResetBits(GPIOB,GPIO_Pin_9); // sel4_B GPIO_ResetBits(GPIOE,GPIO_Pin_0); // sel5_B break; case 3: GPIO_ResetBits(GPIOB,GPIO_Pin_6); // sel1_B GPIO_ResetBits(GPIOB,GPIO_Pin_4); // sel2_B GPIO_SetBits(GPIOB,GPIO_Pin_7); // sel3_B GPIO_ResetBits(GPIOB,GPIO_Pin_9); // sel4_B GPIO_ResetBits(GPIOE,GPIO_Pin_0); // sel5_B break; case 4: GPIO_ResetBits(GPIOB,GPIO_Pin_6); // sel1_B GPIO_ResetBits(GPIOB,GPIO_Pin_4); // sel2_B GPIO_ResetBits(GPIOB,GPIO_Pin_7); // sel3_B GPIO_SetBits(GPIOB,GPIO_Pin_9); // sel4_B GPIO_ResetBits(GPIOE,GPIO_Pin_0); // sel5_B break; case 5: GPIO_ResetBits(GPIOB,GPIO_Pin_6); // sel1_B GPIO_ResetBits(GPIOB,GPIO_Pin_4); // sel2_B GPIO_ResetBits(GPIOB,GPIO_Pin_7); // sel3_B GPIO_ResetBits(GPIOB,GPIO_Pin_9); // sel4_B GPIO_SetBits(GPIOE,GPIO_Pin_0); // sel5_B break; } Get_Temp(); unsigned char a = temp>>4; send_to_uart(a); send_to_uart(0xFF); } } void ADC1_2_IRQHandler(void) { if (ADC_GetITStatus(ADC1, ADC_IT_EOC)) { ADC_ClearITPendingBit(ADC1, ADC_IT_EOC); temp = ADC_GetConversionValue(ADC1); } } void Get_Temp(void) { ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_1Cycles5); ADC_SoftwareStartConvCmd(ADC1, ENABLE); } void send_to_uart(uint8_t data) { while(!(USART1->SR & USART_SR_TC)); USART1->DR=data; } void SetupUSART() { RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,ENABLE); //RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; /* Configure USART1 Tx (PA.09) as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure USART1 Rx (PA.10) as input floating */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_DeInit(USART1); USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); }
  • Сообщения

    • Я живу в стране, где "правит бал" латиница... Спасибо за помощь!
    • На мой взгляд, прежде всего Вы должны хорошо оборудовать своё рабочее место. Когда-то так начинал я. 
      Это приборы первой необходимости, собирая их Вы пройдёте хорошую школу практики и приобретёте опыт. Прежде всего в арсенале Вам понадобится:
      1. Цифровой мультиметр бюджетного уровня, типа DT-830 ( со временем приобретёте более дорогой ). Желательно и стрелочный ( с питанием 3 в и более )
      2. Осциллограф ( ну без него никак ). Он один из главных Ваших помощников.
      3. Генератор НЧ ( без него проверить и грамотно протестировать аудиотехнику не удастся )
           Простейший сможете собрать сами. Будет полезно с точки зрения практики.
      4. Генератор импульсов ( сможете тоже со временем собрать сами )
      5. Паяльный набор в широком ассортименте, инструмент.
      Кратко  изложил арсенал вооружения. Создавая  себе этот костяк, Вы наберётесь практического опыта.
      Не забывайте о элементной базе! Надо чётко знать как работает каждый элемент электроники. Начинать надо, конечно же с простого.
      Можете обращаться напрямую, через почту. У меня много разных таблиц и полезной информации. Чем смогу, постараюсь доходчиво объяснить и помочь.  
       С уважением Вадим  ( email: v.ananov@mail.ru ) 
    • по моему эта фраза несколько длиннее и там ещё присутствуют слова: сделать и продать - наверное Вы их оставили на будущее
    • Данный блок питания можно купить за 12-15$. 2 штуки с суммарной долговременной мощностью 4,5 Квт - 30$. Все его компоненты подобраны для работы 24/365 при любой погоде на GSM станциях, а не ноунеймовый китай. Диапазон напряжений 85÷300V с плавным снижением выходной мощности в диапазоне напряжений 175 - 85В до 50% за счёт применения ККМ. Для гаража это лучше, чем любой другой вариант. Для мобильной эксплуатации, да, затруднительно.
    • С этим, бесспорно, согласен. В случае с усилителями в сотни ватт,  банки электролитов БП и вовсе займут половину платы. Но если делать что-то не шибко мощное, например на так называемых автомобильных ТДА-шках с однополярным питанием или популярных ТДА2030 и 2050, то я не вижу особого смысла разделять платы питания от усилителя.
      Китайцы так и делают, правда. Например в компьютерной акустике. Но доверять Ляо - себя не уважать. Они могут и чисто от балды слепить. Поэтому и решил поднять этот вопрос на сайте - как лучше и почему.
    • Марк Левинсон же , какой то из последних. Схему они никому не показывают ))
    • выложу пока промежуточный вариант) по работе запарка ,сейчас затянется это все( ,Леш еще раз спасибо ,если б не подстрекал я бы не за что за СМД не взялся) ,с ними тоже есть приколы из того что купил две позиции сильно разнятся в номиналах,на фото 18 кОм, к концу недели потихоньку соберу, скину. сильно не ругайте - не волшебник-учусь).с печаткой есть касяк ,кто брал поправьте С9.