Ник:
Пароль:

Контакты

E-mail: info@starterkit.ru
тел.: +7 922 680-21-73
тел.: +7 922 680-21-74
Телеграм: t.me/starterkit_ru

Способы оплаты

User Info


Добро пожаловать,
Guest

Регистрация или входРегистрация или вход
Потеряли пароль?Потеряли пароль?

Ник:
Пароль:

ПользователейПользователей:1
Поисковых ботовПоисковых ботов:2
ГостейГостей:1

ОбновитьПодробнееВсегоВсего:4
Форум » starterkit.ru » Embedded Linux
помогите с генератором меандра
Franky
Добавлено 07.06.2012 20:56 Редактировалось 07.06.2012 22:07
0
Сообщение: 1
Franky
5

Пункты: 5030
Регистрация: 29.06.2010
в файле борды пишу

static void __init set_clk(void)
{
struct clk *pck0;
struct clk *plla;

pck0 = clk_get(NULL, "pck0");
plla = clk_get(NULL, "plla");

at91_set_B_periph(AT91_PIN_PC1, 0); /* PCK0 */

clk_set_parent(pck0, plla);
clk_put(plla);
clk_set_rate(pck0, 1000);
}

потом при инициализации всей перефирии вызываю

set_clk();

На ноге меандр не наблюдается.
Полную чушь наверное пишу, но очень нужно получить точный меандр 1кГц. Для опытов...

ПРАВКА: понял, почитав форум, что лучше не использовать pck. так как там делитель неудобный получается.
Посему смотрю в сторону:
1) PWM
2) PIT
3) TC
какой вариант лучше с точки зрения точности джиттера и есть ли примеры ?
Спуститься к концу Подняться к началу
Персональная информация
sasamy
Добавлено 07.06.2012 22:06 Сообщение: 2
sasamy
4.71

Пункты: 83562
Регистрация: 14.08.2009
По коду - вам нужно добавить в конце после clk_set_rate
clk_enable(pck0);
но помоему 1 кГц не получить - делителя не хватит. Если джиттер не критичен - используйте TC block - там можно любую частоту запрограммировать.
Спуститься к концу Подняться к началу
Персональная информация
Franky
Добавлено 07.06.2012 22:09 Сообщение: 3
Franky
5

Пункты: 5030
Регистрация: 29.06.2010
Цитата
По коду - вам нужно добавить в конце после clk_set_rate
clk_enable(pck0);
но помоему 1 кГц не получить - делителя не хватит. Если джиттер не критичен - используйте TC block - там можно любую частоту запрограммировать.


джиттер всё таки критичен. Лучше постабильнее что-нибудь.
Желательно хотябы кусочек подходящего кода или ссылку на ресурс.
Спуститься к концу Подняться к началу
Персональная информация
sasamy
Добавлено 07.06.2012 23:45 Редактировалось 08.06.2012 00:03 Сообщение: 4
sasamy
4.71

Пункты: 83562
Регистрация: 14.08.2009
Код

#include <mach/at91_tc.h>
...
#define at91_tc_read(reg) __raw_readl(tc0_base + (reg))
#define at91_tc_write(reg, val) __raw_writel((val), tc0_base + (reg))
...
static int clock_1khz(void)
{
void __iomem *tc0_base;
struct clk *tc0_clk;

tc0_base = ioremap_nocache(AT91SAM9260_BASE_TC0, 256);
if (!tc0_base) {
printk("Can't remap TC0 register area\n");
return -1;
}

tc0_clk = clk_get(NULL, "tc0_clk");
if (IS_ERR(tc0_clk)) {
iounmap(tc0_base);
printk("Error: can't find tc0_clk\n");
return -1;
}

clk_enable(tc0_clk);

at91_set_A_periph(AT91_PIN_PA26, 0);

at91_tc_write(AT91_TC_CMR,
AT91_TC_WAVE | AT91_TC_WAVESEL_UP_AUTO
| AT91_TC_ACPA_SET | AT91_TC_ACPC_CLEAR
| AT91_TC_TIMER_CLOCK1 ); // делитель для MCK, см даташит

at91_tc_write(AT91_TC_RC, 4); // число импульсов на период (делитель входящей частоты)
at91_tc_write(AT91_TC_RA, 2); // половина AT91_TC_RC если импульс/пауза 50/50
at91_tc_write(AT91_TC_IDR, -1);
at91_tc_write(AT91_TC_CCR, AT91_TC_SWTRG | AT91_TC_CLKEN);

iounmap(tc0_base);
return 0;
}


пример из старого ядра, в новых clk_get(NULL, "tc0_clk"); помоему не сработает, надо попробовать. Делители подбирайте по даташиту - я числа для примера привел.
Спуститься к концу Подняться к началу
Персональная информация
Franky
Добавлено 07.06.2012 23:51 Редактировалось 07.06.2012 23:56 Сообщение: 5
Franky
5

Пункты: 5030
Регистрация: 29.06.2010
Премного благодарен! Очень выручили. Буду изучать(пока не совсем понятно где именно 1 кГц задаётся)
Мне на сайте AD посоветовали использовать PWM. Это одно и тоже что и TC block? (я имею ввиду джиттер).
можно ли использовать PIT? или он уже занят линуксом?
Спуститься к концу Подняться к началу
Персональная информация
sasamy
Добавлено 08.06.2012 00:07 Сообщение: 6
sasamy
4.71

Пункты: 83562
Регистрация: 14.08.2009
Цитата

можно ли использовать PIT?


Как вы PIT на внешний пин выведете ?? Я так и не понял - что вам нужно ?
Спуститься к концу Подняться к началу
Персональная информация
Franky
Добавлено 08.06.2012 00:17 Редактировалось 08.06.2012 00:21 Сообщение: 7
Franky
5

Пункты: 5030
Регистрация: 29.06.2010
я просто раньше делал так: дёргал в прерывании от PIT ногу и всё)
но это было standalone приложение.
А мне нужно просто получить как можно более качественный сигнал тактовый из SAM9260. Хочу внешние устройства научится тактировать
Спуститься к концу Подняться к началу
Персональная информация
sasamy
Добавлено 08.06.2012 00:31 Сообщение: 8
sasamy
4.71

Пункты: 83562
Регистрация: 14.08.2009
Цитата

дёргал в прерывании от PIT ногу и всё)
но это было standalone приложение.


ну это изврат даже для стандалоне и по точности до TC ему очень далеко, и если это работало с TC 100% будет работать.
Спуститься к концу Подняться к началу
Персональная информация
Dub
Добавлено 08.06.2012 09:01 Сообщение: 9
Dub
5

Пункты: 1141
Регистрация: 14.05.2012
Не хочу плодить темы, поэтому спрошу здесь.
Если требуется тактировать АЦП, что лучше:
1) меандр (коэффициент заполнения 50%)
2) короткий скачок вниз( по cути меадр с коэффициентом заполнения около 90%)
И насколько точнее PWM по сравнению с TC. Или это одно и тоже?
есть ли примеры для PWM под Linux?
Спуститься к концу Подняться к началу
Персональная информация
Franky
Добавлено 08.06.2012 19:34 Редактировалось 08.06.2012 19:56 Сообщение: 10
Franky
5

Пункты: 5030
Регистрация: 29.06.2010
[quote]
Код

#include <mach/at91_tc.h>
...
#define at91_tc_read(reg) __raw_readl(tc0_base + (reg))
#define at91_tc_write(reg, val) __raw_writel((val), tc0_base + (reg))
...
static int clock_1khz(void)
{
void __iomem *tc0_base;
struct clk *tc0_clk;

tc0_base = ioremap_nocache(AT91SAM9260_BASE_TC0, 256);
if (!tc0_base) {
printk("Can't remap TC0 register area\n");
return -1;
}

tc0_clk = clk_get(NULL, "tc0_clk");
if (IS_ERR(tc0_clk)) {
iounmap(tc0_base);
printk("Error: can't find tc0_clk\n");
return -1;
}

clk_enable(tc0_clk);

at91_set_A_periph(AT91_PIN_PA26, 0);

at91_tc_write(AT91_TC_CMR,
AT91_TC_WAVE | AT91_TC_WAVESEL_UP_AUTO
| AT91_TC_ACPA_SET | AT91_TC_ACPC_CLEAR
| AT91_TC_TIMER_CLOCK1 ); // делитель для MCK, см даташит

at91_tc_write(AT91_TC_RC, 4); // число импульсов на период (делитель входящей частоты)
at91_tc_write(AT91_TC_RA, 2); // половина AT91_TC_RC если импульс/пауза 50/50
at91_tc_write(AT91_TC_IDR, -1);
at91_tc_write(AT91_TC_CCR, AT91_TC_SWTRG | AT91_TC_CLKEN);

iounmap(tc0_base);
return 0;
}


пример из старого ядра, в новых clk_get(NULL, "tc0_clk"); помоему не сработает, надо попробовать. Делители подбирайте по даташиту - я числа для примера привел.[/quote]

пытаюсь использовать
TC_FindMckDivisor(1000, BOARD_MCK, &div, &tcclks);
для поиска делителя. Но функция естественно не может найти делитель и возвращает 0.
Как быть. какой делитель выбрать?

Это я к тому что я хочу иметь широкие пределы задания частоты (вплоть до 200 кГц)
Спуститься к концу Подняться к началу
Персональная информация
Форум » starterkit.ru » Embedded Linux