Перейти к содержанию
    

ДЕЙЛ

Свой
  • Постов

    728
  • Зарегистрирован

  • Посещение

  • Победитель дней

    5

Сообщения, опубликованные ДЕЙЛ


  1. По молодости-глупости на днях купил пару вот этих плат.

    http://www.ebay.com/itm/SIM900A-V4-0-Wirel...=item4adb04cfb7

    Терзают смутные сомнения, что в России она не совсем праильно будет работать, но эффективные менеджеры всё равно на других сайтах барыжат их за 3-4 цены.

    Полагаю, что изучать её нужно начинать с перепрошивки. На плате есть вход RX-TX. К нему и нужно подключать провода для смены прошивки? Есть две перемычки, каково их назначение? Сколько вольт питание? Раньше с этим всем дело не имел. Где можно найти схему?

     

    UP1: Можно ли на моей плате заменить SIM900A на SIM900R? Распиновка совпадает за исключением нескольких выводов, которые никуда не заведены.

  2. Неужели самому трудно в любой терминалке настучать команду?

    пока ищу, с какой стороны подойти.

    Как будет выглядеть в терминале такая команда AT+CGDCONT=1,"IP","internet" ?

     

  3. Хочу освоить работу с данным модулем. Заказал две демо-платы, на них есть разъём питания и разъём RS232, который можно подключить напрямую к COM-порту без переходников и преобразователей. Т.е. хочу перед подключением к МК погонять данный модуль командами с ПК. Есть ли уже готовая программа для работы с этим модулем? Такая, на которой есть отдельные кнопки для отправки заранее заготовленных символьных строк АТ-команд.

     

    UP1:

    накопал вот это:

    http://www.seeedstudio.com/wiki/GPRS_Shield_V2.0

    и сама программа:

    http://www.seeedstudio.com/wiki/images/b/b2/Sscom32E.zip

    есть ли что-то подобное, но на русском языке?

  4. Железно заработало :yeah:

    дело было ещё и в указателе стека. В этом прикреплённом проекте в тестовой программе для вызова главной нужно написать такой код:

    unsigned int *VTOR;
    int main()
    {
    VTOR = (unsigned int*)0xE000ED08; //адрес данного регистра из хидера
    *VTOR = 0x7000; //смещение таблицы векторов - из настроек линкера 
    asm ("mov r13, #0x2448"); //запись в регистр стека младших байтов значения указателя стека основной программы, взятого из ячейки с адресом 0x7000;
    asm ("movt r13, #0x1000"); //запись в регистр стека старших байтов значения указателя стека основной программы, взятого из ячейки с адресом 0x7000;
    asm ("B 0x8105"); //Безусловный переход по адресу обработчика прерывания сброса, прочитанного из ячейки 0x7002;
    }

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

     

    теперь попробую назад в загрузчик из главной программы зайти

     

    :bb-offtopic:

    ДЕЙЛ, я, конечно, ничего против не имею, но такая боевая расцветка темы оформления каждый день по несколько часов сидения у монитора глаза не заворачивает на затылок? :)

    :bb-offtopic: Зато оперативка экономится, отключил всё ненужное. Ноуту лет 15, в нём есть привод дискет, два разъёма усб, всамделишный LPT и COM-порты ;) Но зато экран большой и нет отвлекающего выхода в тырнет.

  5. То есть в отладчике переход всё-таки работает? Попробуй пошагать дальше, может ошибка вываливается где-нибудь в другом месте, в отладчике ты до него просто не доходишь.

    Под отладчиком после ассемблерной инструкции перехода программа работает в реальном режиме времени, но её можно остановить и увидеть, что всё крутится в адресах после 7000. Мошть ещё нужно указатель стека на нужное место поставить, как мне посоветовали на другом форуме?

  6. насчёт перескока на 2кб на какой странице мануала написано? Надо попробовать, а симулирование и реальность не всегда совпадают, как я заметил.

     

     

    Поле смещения таблицы векторов. Оно содержит биты [29:7] смещения таблицы относительно начального адреса. То есть надо взять смещение 0x7000, взять из него биты 29:7, получившееся число 0xE0 записать в биты 29:7 регистра. Это то же самое, что и запись в регистр числа 0x7000.

    пробовал разные варианты - записывал 0x380000 и 0x7000, в отладчике наблюдалось число 0xE0.

    Не понял.

    Имею ввиду, что программа из флеши запускается в следующем шаге после строки B 0x8105 при нажатии кнопки F10 в пошаговом режиме отладки, т.е. переходит в то место и запускает программу, а когда отключаю JTAG и нажимаю на сброс, то никаких переходов нет, контроллер не шевелится.

  7. Пока повезло. :rolleyes:

    Недостатков сразу несколько.

    ......

    Согласен с перечисленным и у меня это всё предусмотрено, а на схеме показал принцип переноса синусоиды в положительную область для оцифровки. В расходомере питание прецизионное, имеется двойная гальваническая развязка от питающей сети, в металлоискателе реализован динамический режим, т.е. значение нуля постоянно вычисляется по скользящему среднему в течение нескольких секунд, а фиксируются быстрые изменения сигнала. Проблем пока нет.

     

     

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

    В хидере 35 прерываний и добавим 16 исключений, как написано в руководстве на ядро, получили 51, ближайшая степень двойки - 64, умножаем на 4 и получим 0x100. Этому числу должен быть кратен адрес таблицы векторов, т.е. 0x7000 подходит.

    Далее читаю описание полей регистра VTOR:

    Бит 29 TBLBASE - расположение таблицы в оперативке(1) или во флеш(0)

    Биты 28:7 TBLOFF - Смещение таблицы относительно начала области кода или области ОЗУ,т.е. к 0x7000 добавляем справа 7 нулевых битов и получаем 0x380000 и записываем это число в регистр VTOR.

     

    Второе. Никаких жестко заданных 0x8105! При следующей компиляции этот адрес может быть совсем другим. Я же сказал, как его достать: читаешь значение из второго вектора в таблице основного ПО, которая всегда находится в известном (определенном тобой) месте.

    Пока не трогаю записанные данные по адресу 0x7000, т.е. никуда ничего не перемещаю, а пытаюсь маленькой программой запустить большую, расположеннуюв другом месте памяти. И адрес 8105 не меняется в моём случае.

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

     

    Исходя из твоего третьего скриншота, тебе надо прочитать содержимое по адресу 0x7004, судя по скриншоту оно было равно 0x8105, и перейти в этот самый 0x8105.

    Написал две строки

    *VTOR = 0x380000; //смещение таблицы относительно начала области кода (0x0000) 0x7000 передвинуты на 7 бит влево, т.к. смещение записывается в битах 28:7
    asm ("B 0x8105");

    Нивкакую не работает. Что ещё упустил и как правильно написать для перехода к программе, начинающейся с адреса 0x7000?

  10. Это нехорошая схема, не учите плохому... :biggrin:

    Она работает в двух приборах - металлоискатель и расходомер при условии, что сигнал находится в линейной области работы операционника и питание не плавает. Очень интересно почитать комментарии по поводу этой схемы. Какие в ней подводные камни?

     

  11. Собираюсь использовать АЦП AD7606. В задаче оцифровки сигнала напряжения промышленной сети (RMS 380В - номинальное заначение). Озадачился расчётом входных цепей. Понятно что это будет делитель. Непонятна конечная схемотехника этого делителя с учётом необходимых защит.

    В каких пределах меняется напряжение?

    Будем считать, что плюс-минус 20%

     

    Я сильно не мудрил бы с делителями, а поставил бы понижающий трансформатор перед входом АЦП, если он биполярный. Если однополярный, то сигнал со вторичной обмотки просуммировал бы с постоянным напряжением и подал бы на АЦП. Если в реальном времени оцифровывать не нужно, т.е. не нужно следить за формой синуса, то можно применить пиковый детектор. Ну и при применении разделительного понижающего трансформатора безопасность повышается - если где-то на плате коротнёт или пробьёт, то прибор не покалечит пользователя.

     

    В прилепленном рисунке схема, которую сам реализовывал для такого дела в случае однополярного АЦП(МК Atmega32).

    Применял двухполярное питание +6В..-6В, от которого питал повторитель. От этого же источника питал стабилизатор +5В, но включал так, как показано на схеме, т.е. схема стабилизатора и МК не использует и не видит среднюю точку. Подстроечный резистор нужно выставить так, чтобы на входе АЦП была половина опорного напряжения при отсутствии сигнала на входе (в моём случае 2.5В было). Размах сигнала должен вписываться в пределы от 0 до опорного(5В), с этим понятно. Регулируется этот размах коэффициентом трансформации или коэффициентом усиления усилителя.

     

    Ещё нужно на вход АЦП поставить обычную защиту из двух диодов.

    post-79085-1412687330_thumb.jpg

  12. Так по этому и не работал - передача параметрами command и result полностью забивали то, что вы сделали в ассемблерной вставке. Причем меняли правильные значения в регистрах (после ассемблерной вставки) на неправильные (из модифицированного command)

    не работало по причине неправильной программы, это я уже выяснил :) Этот вопрос можно пока закрыть. Лучше посоветуйте в теме про стартовый загрузчик.

  13. ..а если выкачать все, а в память класть сколько места есть, а потом выдавать тот де блок но окно сдвигать и так пока блок не кончиться.

    Насколько помню, в конце сектора имеется какая-то контрольная сумма, поэтому для надёжности его нужно весь в буфер считывать и проверять правильность данных. Этот момент уточни.

  14. Покопался в настройках линкера, нашёл настройки линкера:

    Config->Edit->Linker configuration file editor->Vector Table-> .intvec start = 0x7000

    Config->Edit->Linker configuration file editor->Memory Regions-> ROM = 0x7000 - 0x7FFFF

    После компилирования и запуска в пошаговом режиме видно, что программа раположена по адресу, начиная с 0x7000, на этом этапе всё работает нормально - данные бегут из UART0.

    Получается, что программа уже нормально записана в память и работоспособна.

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

    Пишу такой текст:

    main()
    {
    asm ("B 0x7000");
    }

    Перебрал несколько возможных адресов, но всегда зависает в Hard Fault.

     

     

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

    ......

    - Цель безусловного перехода - обработчик прерывания сброса основного ПО. Адрес обработчика находится в известном векторе прерывания. Таблица векторов прерываний находится в начале области, отведенной под основное ПО.

    В каком известном векторе прерывания находится адрес обработчика? Как узнать этот адрес?

     

     

    - Для перехода к основному ПО необходимо (именно в такой последовательности):

    1. запретить все прерывания

    2. привести состояние использованной периферии к начальному

    3. задать в регистре смещения новое положение таблицы векторов прерываний основного ПО

    4. совершить переход

    Написал маленькую тестовую программу без подключения библиотек и лишних файлов

    unsigned int *VTOR
    int main()
    {
    VTOR = (unsigned int*)0xE000ED08; //адрес регистра смещения таблицы
    *VTOR = 0x7000;  //смещение адреса таблицы веторов прерываний
    asm ("B 0x7000"); //адрес перехода
    }

    Т.е.

    1. Прерывания не разрешал, близко к ним не подходил в этом коде.

    2. Переферию не трогал

    3. С этим вопрос - как узнать адрес?

    4. По какому адресу переходить? Как его узнать?

     

    UP1: в прикреплённом архиве проект основного ПО и второй проект тестовой программы, которая должна запускть основное ПО

    post-79085-1412629711_thumb.jpg

    post-79085-1412629729_thumb.jpg

    post-79085-1412629748_thumb.jpg

    ______________________________________________.rar

  15. У меня было ошибочное предположение, что адреса таблиц нужно вписывать в регистры вручную перед вызовом IAP, что я и делал:

    asm ("mov  r0, #0x6000"); //Запись в регистры отдельно младшие 2 байта
    asm ("movt r0, #0x2000"); //и старшие два байта адресов таблиц
    
    asm ("mov  r1, #0x6100");
    asm ("movt r1, #0x2000");

    Поэтому в моём представлении инкременты ничего не меняли, но в любом случае вариант кода из первого поста не работал.

  16. Спасибо, заработало :-)

     

    Выкинул ассемблер, упростил и в итоге получился работающий код:

    #include "iolpc1778.h"
    #include "LPC17xx.h"
    #define IAP_LOCATION 0x1fff1ff1 //точка входа в IAP (страница 896 мануала)  
    unsigned int command[5];
    unsigned int result[2];
    unsigned int  *test;
    typedef void (*IAP)(unsigned int[], unsigned int[]);  
    void main(void)
    {
    { //INIT 
    SCS     |= 0x20;          //подключение осциллятора 12МГц 
    
    while(!( SCS & 0x40 )) {} //ожидание запуска 
    
    PLL0CON |= 0x01;          //включение PLL0
    PLL0CFG |= 0x09;          //умножение частоты тактирования на (1+9) - 120МГц
    PLL0FEED = 0xAA;          //
    PLL0FEED = 0x55;          //
    CCLKSEL |= 0x100;         //тактирование CPU от PLL0
    }
    test  = (unsigned int*)0x20001004;
    *test = 0xAA;
    
    
    
    IAP iap_entry;
    iap_entry = (IAP) IAP_LOCATION;
    
    
    
    //_______ПОДГОТОВИТЬ СЕКТОР К ЗАПИСИ_______//
    {
    
    command[0] = 50; //код команды
    command[1] = 4;  //начальный номер сектора
    command[2] = 4;  //конечный номер сектора
    
    iap_entry (command, result); 
    }
    //_______ПОДГОТОВИЛИ СЕКТОР К ЗАПИСИ______// 
    
    
    
    
    //_______СТЕРЕТЬ СЕКТОР_______//
    {
    
    command[0] = 52;     //код команды
    command[1] = 4;      //начальный номер сектора
    command[2] = 4;      //конечный номер сектора
    command[3] = 120000; //системная тактовая частота в кГц
    
    iap_entry (command, result); 
    }
    //_______СТЁРЛИ СЕКТОР______// 
    
    //_______ПОДГОТОВИТЬ СЕКТОР К ЗАПИСИ_______//
    {
    
    command[0] = 50; //код команды
    command[1] = 4;  //начальный номер сектора
    command[2] = 4;  //конечный номер сектора
    
    iap_entry (command, result); 
    }
    //_______ПОДГОТОВИЛИ СЕКТОР К ЗАПИСИ______// 
    
    
    
    
    //_______КОПИРОВАТЬ ОПЕРАТИВНУЮ ПАМЯТЬ ВО ФЛЕШ_______//
    {
    
    command[0] = 51;         //код команды
    command[1] = 0x4000;     //начальный адрес перезаписываемой флеш
    command[2] = 0x20001000; //начальный адрес оперативной памяти, откуда нужно копировать 
    command[3] = 512;        //число байт для копирования
    command[4] = 120000;     //системная тактовая частота в кГц
      
    iap_entry (command, result); 
    }
    //_______СКОПИРОВАЛИ СЕКТОР______// 
    
    while(1)
    {
       test  = (unsigned int*)0x4004;
    }
    }

     

    Интересно узнать, в чём суть подготовки памяти? Со стиранием вроде понятно - наверно FFFFFFFами заполняет всё. И ещё есть не совсем понятная команда заполнения пробелами. Правильно я понимаю, что 0x1fff1ff1 есть адрес начала отдельной программы IAP?

  17. Читать документацию на среду разработки. Или хотя бы указать ее название - возможно кто-то и подскажет. Но читать полезнее :)

    среда IAR

     

    Вы зарезервировали для IAP место в конце ОЗУ?

    В мануале написано, что нужно зарезервировать верхние байты. Что имеется ввиду под верхними байтами, если считать за начало адрес 0x2000000, а за конец 0x2008000? Эти 32 байта распложены в области 0x2000000 - 0x200001F или в другом конце?

     

  18. Перед командой стирания надо выполнить команду подготовки сектора. Запись в регистры асм-вставками бессмысленна - вы делаете то же самое вызывая iap_entry() с параметрами. Во стальном похоже на правду. Вы зарезервировали для IAP место в конце ОЗУ?

    С этим тоже вопрос. Как зарезервировать место в памяти?

  19. Решил данный вопрос задать в отдельной теме, ответвив от темы про стартовый загрузчик http://electronix.ru/forum/index.php?showt...15&start=15

    Там подсказали насчёт организации записи флеш из пользовательской программы. Сделал по мануалу, т.к. примеров пока не видел. Получилось вот так:

    #include "iolpc1778.h"
    #include "LPC17xx.h"
    #define IAP_LOCATION 0x1fff1ff1 //точка входа в IAP (страница 896 мануала)  
    unsigned long *command;
    unsigned long *result;
    unsigned int  *test;
    typedef void (*IAP)(unsigned int*, unsigned int*);  
    void main(void)
    {
    { //INIT 
    SCS     |= 0x20;          //подключение осциллятора 12МГц 
    
    while(!( SCS & 0x40 )) {} //ожидание запуска 
    
    PLL0CON |= 0x01;          //включение PLL0
    PLL0CFG |= 0x09;          //умножение частоты тактирования на (1+9) - 120МГц
    PLL0FEED = 0xAA;          //
    PLL0FEED = 0x55;          //
    CCLKSEL |= 0x100;         //тактирование CPU от PLL0
    }
    test  = (unsigned int*)0x20001004; //записал контрольный байт в копируемую область RAM
    *test = 0xAA;
    
    
    
    IAP iap_entry;                              //так в мануале написано
    iap_entry = (IAP) IAP_LOCATION; //---//---
    
    
    
    //_______СТЕРЕТЬ СЕКТОР_______//
    {
    result  = (unsigned long*)0x20006100;   //адрес расположения таблицы результатов
    command = (unsigned long*)0x20006000;   //адрес таблицы параметров
    
    *command = 52; //код команды
    *command++;
    *command = 4;  //начальный номер сектора
    *command++;
    *command = 4;  //конечный номер сектора
    *command++;
    *command = 120000; //системная тактовая частота в кГц
    
    asm ("mov  r0, #0x6000"); //Запись в регистры отдельно младшие 2 байта
    asm ("movt r0, #0x2000"); //и старшие два байта адресов таблиц
    
    asm ("mov  r1, #0x6100"); 
    asm ("movt r1, #0x2000");
    
    iap_entry (command, result); 
    }
    //_______СТЁРЛИ СЕКТОР______// 
    
    
    
    
    
    //_______ПОДГОТОВИТЬ СЕКТОР К ЗАПИСИ_______//
    {
    result  = (unsigned long*)0x20006100;   //адрес расположения таблицы результатов
    command = (unsigned long*)0x20006000;   //адрес таблицы параметров
    
    *command = 50; //код команды
    *command++;
    *command = 4;  //начальный номер сектора
    *command++;
    *command = 4;  //конечный номер сектора
    
    asm ("mov  r0, #0x6000"); //Запись в регистры отдельно младшие 2 байта
    asm ("movt r0, #0x2000"); //и старшие два байта адресов таблиц
    
    asm ("mov  r1, #0x6100"); 
    asm ("movt r1, #0x2000");
    
    iap_entry (command, result); 
    }
    //_______ПОДГОТОВИЛИ СЕКТОР К ЗАПИСИ______// 
    
    
    
    
    
    
    
    //_______КОПИРОВАТЬ ОПЕРАТИВНУЮ ПАМЯТЬ ВО ФЛЕШ_______//
    {
    result  = (unsigned long*)0x20006100;   //адрес расположения таблицы результатов
    command = (unsigned long*)0x20006000;   //адрес таблицы параметров 
    
    *command = 51;         //код команды
    *command++;
    *command = 0x4000;     //начальный адрес перезаписываемой флеш
    *command++;
    *command = 0x20001000; //начальный адрес оперативной памяти, откуда нужно копировать 
    
    *command++;
    *command = 512;        //число байт для копирования
    *command++;
    *command = 120000;     //системная тактовая частота в кГц
    
    
    asm ("mov  r0, #0x6000"); //Запись в регистры отдельно младшие 2 байта
    asm ("movt r0, #0x2000"); //и старшие два байта адресов таблиц
    
    asm ("mov  r1, #0x6100"); 
    asm ("movt r1, #0x2000");
    
    iap_entry (command, result); 
    }
    //_______СКОПИРОВАЛИ СЕКТОР______// 
    
    
    
    
    while(1)
    {
       test  = (unsigned int*)0x4004; //для просмотра ячейки в отладчике в пошаговом режиме. 
    }
    }

     

     

    Работать почему-то не хочет - как было во флеш FFFFFFFFFFFF, так и остались. Ещё в мануале написано, что содержимое регистров r0 и r1 остаётся постоянным во время работы с флеш-памятью, но у меня в пошаговом режиме видно, что после функции iap_entry (command, result); они меняются. Так же там написано, что в регистры r0 и r1 записываются начальные адреса таблиц параметров и результатов. Можно ли в моём коде избавиться от ассемблерных вставок, т.к. каждый раз вручную назначать адреса таблиц в памяти неудобно и нежелательно. Ещё там написано, что верхние 32 байта RAM не должны использоваться пользовательской программой, но как программе запретить пользоваться этими байтами?

     

    UP1: добавил файл проекта в IAR

    20141001LPC.rar

  20. У них нет возможности записи в ячейку. Вы можете записать только блок. Пример там писать не стали - вся запись сводится к загрузке 4 регистров и вызвове одной функции IAP. Читайте раздел Flash Memory до просветления.

    Но ведь хочется спросить и тут разжёваный ответ получить :rolleyes: Спасибо за направляющий ответ, буду копать.

     

    Как в общих чертах происходит запись блока? Какие шаги нужно проделать?

  21. Пока в исходник загрузчика глубоко не влазил. Хочу попробовать что-либо записать во флеш из программы.

     

    т.е. если написать вот так:

    adres = (unsigned int*)0x20000200; //область оперативной памяти
    *adres = 0x12345678;

    то всё нормально - в ячейку с указанным адресом записывается число, а если написать вот так

    adres = (unsigned int*)0x1000; //область флеш-памяти
    *adres = 0x12345678;

    то ничего не записывается. Тут нужно предварительно какие-то настройки делать. В мануале что-то написано, но нет примеров.

    Хотелось бы увидеть самый простой пример включения возможности записи в ячейку флеш. МК LPC1778

  22. Тут надо разделить магнитные помехи и электрические. От магнитных помех спасёт пермаллой, а от высокочастотных электрических обычно экранируют не сплошным металлом, а сеткой с круглыми отверстиями, как Вы наверно видели внутри сотовых телефонов. Если правильно помню из курса технической электродинамики, такие отверстия называются вырожденными волноводами, т.е. такие волноводы, которые физически не могут пропустить электромагнитные волны выше определённой частоты. На 100% правильность совета не претендую ввиду почти полностью забытых мной лекций по СВЧ, но я бы поэкспериментировал бы с дырчатыми экранами.

  23. Ах да, пардон, конечно есть. кварцевый резонатор на 25 МГц (подключен к XT2)

    А если заменить кварц? Среди них тоже бывают бракованные. И ещё смущает такая частота, для MSP430 это как-то многовато, я разгонял PLL максимум до 20МГц, а кварц ставил до 8-10 МГц. Может МК работает на пределе частоты и повышение температуры его добивает? Остальной код нормально работает?

×
×
  • Создать...