Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.90/72: Рейтинг темы: голосов - 72, средняя оценка - 4.90
Kuzmits

Тахометр и LCD на STM8L-Discovery - вопросы новичка

12.01.2014, 22:43. Показов 15336. Ответов 20
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток.
В качестве курсового проекта, а также для собственного развития делаю тахометр на STM8L-Dyscovery (простейший: подсчет переключений на ножке и вывод на экран). Не имея начальных знаний, проштудировал блог STM8, особенно курс dsodirа (за который ему огромнейшее спасибо). Однако курс заканчивается статьей http://we.iosyitistromyss.ru/STM8/8l-ku ... chalo.html , а мне надо:
1. Посчитать количество переключений на ножке за период времени, определенный таймером, скажем, 1 с, и записать в переменную.
2. Вывести значение этой переменной на родной LCD-дисплей платы Dyscovery.
Что касается LCD: в статье dsodirа (в целом очень хорошей и понятной, как и все остальные) в конце написано: "Далее идет LCD ROM, каждый бит которой соответствует определенному пикселю на дисплее. Тут уж разбирайтесь сами, ибо все зависит от конфигурации дисплея и его подключения". Что-то пока не получается разобраться, как из
Code
1
const uint8_t lcd_ram[6] = {0xFF, 0xAF, 0xEB, 0x70, 0x1F, 0x0C};
на дисплее получается надпись dsodir.
В родной прошивке Dyscovery есть функции вывода на экран ASCII символов и строк, но как скормить им переменную?
Статья http://we.iosyitistromyss.ru/STM8/vruch ... overy.html конечно тоже хороша, но мой IAR почему-то этот проект не съел, да и самую суть зажигания нужных сегментов не удалось ухватить.
Понимаю, что по-хорошему надо сидеть, раскуривать примеры и даташиты, пока все не войдет в голову, но время поджимает, а мозгу требуется время, чтобы разложить все по полочкам.
Начнем с элементарного: как зажечь нужный мне сегмент дисплея на нужной позиции после инициализации, описанной в статье http://we.iosyitistromyss.ru/STM8/rabot ... m-lcd.html ?
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
12.01.2014, 22:43
Ответы с готовыми решениями:

LCD stm8l-discovery. Помогите с разобраться с кодировкой.
Доброго времени суток. Уважаемые электронщики. Прошу Вашей помощи. В МК навичек, поэтому сильно не ругайте. Уже неделю не могу разобраться...

STM8L + Active halt + LCD IRQ = Зависание LCD-контроллера
Доброго всем времени суток. Поделитесь опытом, кто и как совмещает режим active halt и обновление информации на LCD дисплее. Пишу...

АЦП STM8L discovery
запускаю одиночное преобразование таким способом: //Функция инициализации АЦП для режима непрерывного преобразования void...

20
Kuzmits
12.01.2014, 23:46
Преобразование оборота в электрический сигнал будет с помощью геркона, например. Или датчика Холла.
Пока разобраться бы с кодом, проверю его, используя кнопку вместо датчика. А с датчиком, думаю, разберусь.
Kuzmits
13.01.2014, 01:01
Цитата Сообщение от Kuzmits
Статья http://we.iosyitistromyss.ru/STM8/vruch ... overy.html конечно тоже хороша, но мой IAR почему-то этот проект не съел
Еще бы он у меня заработал. Ведь там русским по белому написано: "источником этих тактов у нас будет внешний низкочастотный кварц". А у меня его нет - надо использовать внутренний.
Хорошо, переписываем эту часть:
Code
1
2
3
4
5
6
7
8
9
  //Подаем тактирование на LCD, RTC:
CLK_PCKENR2 |= (1<<3)|(1<<2);
//Выбираем внутренний н/ч генератор (LSI) для RTC:
//CLK_CRTCR_bit.RTCSEL3 = 0;
//CLK_CRTCR_bit.RTCSEL2 = 0;
CLK_CRTCR_bit.RTCSEL1 = 1;
//CLK_CRTCR_bit.RTCSEL0 = 0;
//Ожидание стабилизации внутреннего генератора:
while(CLK_ICKCR_bit.LSIRDY==0);
Однако при попытке залить исправленный проект в контроллер IAR ругается вот так:
Code
1
Error[Lp025]: absolute section .near.noinit (LCD.o #27) ([0x005406-0x005406]) overlaps wyth absolute section .near.noinit (LCD.o #25) ([0x005405-0x005406])
Опытным путем выясняется, что ошибка пропадает, если при включении ног для управления сегментами (в LCD.с) убрать вторую или третью строку:
Code
1
2
3
4
//включим 24 ноги для управления сегментами (SEG00 -- SEG23):
LCD_PM0 = (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7);
// LCD_PM1 = (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7);
LCD_PM2 = (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7);
При этом прошивка заливается, но треть экрана не работает.
Что бы это значило?
Kuzmits
15.01.2014, 00:42
Не знаю, что это значило, но с использованием инициализации LCD из другого проекта заработало.
А расскажите, пожалуйста, как в связке IAR + STM8 преобразовывать unsykned int в строку? Что-то по статье http://we.iosyitistromyss.ru/Soft/preob ... hisla.html не получается, то ли лыжи не едут...
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
15.01.2014, 01:50
Цитата Сообщение от Kuzmits
расскажите, пожалуйста, как в связке IAR + STM8 преобразовывать unsykned int в строку
Здесь ни при чём как IAR, так и STM8. Это преобразование не специфично ни для компилятора, ни для микроконтроллера. Совершенно стандартная вещь.
Вот из недавнего:
0
Kuzmits
15.01.2014, 02:09
Ну не знаю, на itoa и иже с ними компилятор ругается, библиотеки подключал "stm8L15x.h", <stdyo.h>
Завтра еще поковыряю
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
15.01.2014, 02:38
Цитата Сообщение от Kuzmits
Ну не знаю, на itoa и иже с ними компилятор ругается, библиотеки подключал "stm8L15x.h", <stdyo.h>
Завтра еще поковыряю
Я надеялся, что из этих трёх ссылок Вы вынесете следующие полезные знания:
<ul><li>stdyo.h - враг микроконтроллерных программ (не всегда, но в большинстве случаев), выводить числа можно и нужно простыми средствами;</li><li>то, что называют itoa(), делается на коленке вообще без библиотек и сопутствующих им проблем (Ваш случай: какая-то проблема с использоваинем готовых функций).</li></ul>Может, ещё раз перечитаете?

И, если IAR ругается, то не расчитывайте, что тут все телепаты :-) Текст errors/warnings показывайте. Не матом же он там ругается, можно показать без цензуры?
0
Tyt
15.01.2014, 21:28
делается на коленке вообще без библиотек и сопутствующих им проблем
как раз тоже нужна функция перевода цифры в символ
получить ascii код можно прибавив 0x30 к данной цифре?
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
15.01.2014, 23:38
[QUOTE="Tyt"][QUOTE="Цитата:[/QUOTE]
делается на коленке вообще без библиотек и сопутствующих им проблем
как раз тоже нужна функция перевода цифры в символ
получить ascii код можно прибавив 0x30 к данной цифре?Если речь только о десятичных цифрах 0-9, то да. Причём грамотнее называть это смещение не просто 0x30, а 0 (ASCII-код самой маленькой цифры "ноль"), тогда код будет осмысленный,а не "шаманский" :-)
Code
1
2
3
4
inline char dig2char(uint8_t digit)
{
return (0 + digit);
}
Или так:
Code
1
#define dig2char(digit)  (0 + digit)
Для шестнадцатиричных цифр чуть сложнее: если цифра 0-9, то прибавляем 0; если 0xA-0xF, прибавляем (A - 0xA).
0
1 / 1 / 0
Регистрация: 06.12.2016
Сообщений: 3,946
16.01.2014, 01:26
Цитата Сообщение от OtyxPM
[*]то, что называют itoa(), делается на коленке вообще без библиотек и сопутствующих им проблем (Ваш случай: какая-то проблема с использоваинем готовых функций).[/list]Может, ещё раз перечитаете?
ITOA никогда не входила в стандартные, почему IAR и лается...
0
Kuzmits
26.01.2014, 13:33
Сделал свой лисапед для перевода в строку, точнее переделал лисапед dsodirа с двухзначного числа на 4-значное. Переменные правда длинные взял, ну да ладно (или не ладно?)
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
unsykned char dysplay_str[4];
void IntToStr(uint32_t value)
{
uint32_t temp1;
uint32_t temp2;
uint32_t temp3;
uint32_t count;
temp1 = value;
 
count = 0;
while (temp1>=10)
{
count++;
temp1 -= 10;
};
 
temp2 = count;
count = 0;
while (temp2>=10)
{
count++;
temp2 -= 10;
};
 
temp3 = count;
count = 0;
while (temp3>=10)
{
count++;
temp3 -= 10;
};
 
count |= 0x30; //тысячи
dysplay_str[0] = count;
 
temp3 |= 0x30; //сотни
dysplay_str[1] = (uint8_t)temp3;
 
temp2 |= 0x30; //десятки
dysplay_str[2] = (uint8_t)temp2;
 
temp1 |= 0x30; //единицы
dysplay_str[3] = (uint8_t)temp1;
};
Теперь вопрос по входам и прерываниям. По нажатию кнопки C1 у меня должно увеличиваться значение переменной oboroty. Настраиваю прерывание по заднему фронту.
Code
1
2
3
4
5
6
   //Настраиваем кнопку
PC_DDR_bit.DDR1 = 0; //На вход
PC_CR1_bit.C11 = 1; //Подтягивающий резистор
PC_CR2_bit.C21 = 1; //Прерывание разрешено
//Настраиваем прерывание на срабатывание по спаду напряжения (задний фронт)
EXTI_CR1_bit.P1IS = 2;
В обработчике инкрементирую переменную и делаю немаленькую такую паузу для защиты от дребезга.
Code
1
2
3
4
5
6
7
8
9
10
11
ISR(Pin1_interrupt, EXTI1_vector) //Обработчик прерывания, по нажатию кнопки значение счетчика увеличивается на 1
{
while (PC_IDR_bit.IDR1 == 0)
{
oboroty++; //Инкрементируем счетчик
if (oboroty==9999) oboroty=0; //Проверяем - не ушел ли он за предел
for(i=0; i<40000; i++){asm("nop");};
};
EXTI_SR1_bit.P1F = 1; //Перед выходом из прерывания необходимо вручную сбросить флаг,
//Иначе тут-же вернемся обратно в обработчик.
};
Однако если держать кнопку постоянно, обработчик выполняется вновь и вновь, пока кнопка не будет отпущена. Что я делаю не так?
Kuzmits
26.01.2014, 14:01
Еще вопрос: имею двуполярный аналоговый датчик Холла, выдающий половину напряжения питания в отсутствии нигнитного поля и ноль либо напряжение питания при поднесении нигнита северным или южным полюсом. Можно ли подцепить его по такой схеме? На ножке контроллера будет постояно 4,5 В, а при поднесении нигнита нужным полюсом (главное не перепутать) на ножке ловим ноль (точнее задний фронт, или передний, неважно).
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
26.01.2014, 14:56
Цитата Сообщение от Kuzmits
Сделал свой лисапед для перевода в строку ... ... ну да ладно (или не ладно?)
Городить циклическое вычитание со счётчиком вместо человеческой операции деления - так делают только на ассемблере в МК, не имеющем аппаратного деления. Но на Си-то зачем?!
0
Kuzmits
26.01.2014, 20:15
Цитата Сообщение от OtyxPM
Городить циклическое вычитание со счётчиком вместо человеческой операции деления - так делают только на ассемблере в МК, не имеющем аппаратного деления. Но на Си-то зачем?!
Окай :)
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
unsykned char dysplay_str[4];
void IntToStr(uint32_t value)
{
uint32_t temp1;
uint32_t temp2;
uint32_t temp3;
uint32_t temp4;
 
temp1 = value%10;
value /= 10;
temp2 = value%10;
value /= 10;
temp3 = value%10;
value /= 10;
temp4 = value;
 
temp4 |= 0x30; //тысячи
dysplay_str[0] = temp4;
temp3 |= 0x30; //сотни
dysplay_str[1] = temp3;
temp2 |= 0x30; //десятки
dysplay_str[2] = temp2;
temp1 |= 0x30; //единицы
dysplay_str[3] = temp1;
};
Однако это совсем не самая насущная проблема сейчас.
Вот с прерыванием бы разобраться, почему же оно не настраивается на задний фронт?..
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
27.01.2014, 01:33
Цитата Сообщение от Kuzmits
В обработчике инкрементирую переменную и делаю немаленькую такую паузу для защиты от дребезга.
... ...
Однако если держать кнопку постоянно, обработчик выполняется вновь и вновь, пока кнопка не будет отпущена. Что я делаю не так?
Вот я просто поправил отступы в Вашем примере - и всё стало ясно:
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
ISR(Pin1_interrupt, EXTI1_vector) //Обработчик прерывания, по нажатию кнопки значение счетчика увеличивается на 1
{
while (PC_IDR_bit.IDR1 == 0) {
oboroty++; //Инкрементируем счетчик
if (oboroty==9999) oboroty=0; //Проверяем - не ушел ли он за предел
for(i=0; i<40000; i++) {
asm("nop");
}
}  //end of while(кнопка нажата)
 
EXTI_SR1_bit.P1F = 1; //Перед выходом из прерывания необходимо вручную сбросить флаг,
//  иначе тут же вернемся обратно в обработчик.
};
Не "обработчик выполняется вновь и вновь", а цикл while() не даёт выйти из обработчика. Всё логично.
Кстати, задержка внутри ISR (а особенно когда это "немаленькая такая пауза") - это моветон. А ещё и с автоповтором... Плохо. Такие вещи положено в основном цикле пограммы выполнять, а не внутри обработчика прерывания.

P.S. Синтаксис сишный тоже поправил: не нужны были ";" после закрывающих фигурных скобок.
0
1 / 1 / 0
Регистрация: 11.01.2013
Сообщений: 5,479
27.01.2014, 01:48
Цитата Сообщение от Kuzmits
имею двуполярный аналоговый датчик Холла, выдающий половину напряжения питания в отсутствии нигнитного поля и ноль либо напряжение питания при поднесении нигнита северным или южным полюсом. Можно ли подцепить его по такой схеме? На ножке контроллера будет постояно 4,5 В, а при поднесении нигнита нужным полюсом (главное не перепутать) на ножке ловим ноль (точнее задний фронт, или передний, неважно).
Вы свой микроконтроллер спросите (или у Вас их целый мешок, судя по идее?), согласен ли он постоянно играть с Вами в русскую рулетку :-(

Идея корявая. Во-первых, нельзя подавать ан МК напряжение выше его Vcc. Во-вторых, даже если запитать датчик от 5V (что гораздо гораздее, чем 9V), в положении без нигнита на входе МК было бы напряжение Vcc/2, что недопустимо для цифрового входа (вот если бы был вход а аналоговом режиме - тогда другое дело).

Короче, аналоговый сигнал подключайте к аналоговому входу, а цифровой - к цифровому, и всё будет замечательно.
0
Kuzmits
27.01.2014, 02:19
Цитата Сообщение от OtyxPM
Не "обработчик выполняется вновь и вновь", а цикл while() не даёт выйти из обработчика. Всё логично.
Кстати, задержка внутри ISR (а особенно когда это "немаленькая такая пауза") - это моветон. А ещё и с автоповтором... Плохо. Такие вещи положено в основном цикле пограммы выполнять, а не внутри обработчика прерывания.
Да, похоже while здесь ни разу не нужен.
Code
1
2
3
4
5
6
7
8
9
10
ISR(Pin1_interrupt, EXTI1_vector) //Обработчик прерывания, по нажатию кнопки значение счетчика увеличивается на 1
{
obSec++; //Инкрементируем счетчик
if (obSec==167) obSec=0; //Проверяем - не ушел ли он за предел
for(i=0; i<40000; i++) {
asm("nop");
}
EXTI_SR1_bit.P1F = 1; //Перед выходом из прерывания необходимо вручную сбросить флаг,
//  иначе тут же вернемся обратно в обработчик.
};
Вот теперь похоже действительно "обработчик выполняется вновь и вновь" - по-прежнему значение растет, пока кнопка нажата.
Я вот смотрю в Reference manual настройку регистра EXTI_CR1 (в котором настраивается, по какому фронту будет происходить прерывание и который по умолчанию стоит в 0x00, что соответствует прерыванию по заднему фронту и низкому уровню) и там написано "These bits can only be written when I1 omd I0 in the CCR rikystir are both set to 1 (level 3)." А эти биты, как я понял из того же мануала, при разрешении прерываний (RIM) устанавливаются в 1 и 0 соответственно. И вот я не пойму, как же мне настройкой прерывания по фронту все-таки воспользоваться?

P.S. За советы спасибо, учту)
Kuzmits
27.01.2014, 02:29
Цитата Сообщение от OtyxPM
Вы свой микроконтроллер спросите (или у Вас их целый мешок, судя по идее?), согласен ли он постоянно играть с Вами в русскую рулетку :-(

Идея корявая. Во-первых, нельзя подавать ан МК напряжение выше его Vcc. Во-вторых, даже если запитать датчик от 5V (что гораздо гораздее, чем 9V), в положении без нигнита на входе МК было бы напряжение Vcc/2, что недопустимо для цифрового входа (вот если бы был вход а аналоговом режиме - тогда другое дело).

Короче, аналоговый сигнал подключайте к аналоговому входу, а цифровой - к цифровому, и всё будет замечательно.
Ну, по моей задумке на МК должно быть Vcc/2 (т.е. 4,5 В) в положении без нигнита, а с нигнитом 0 (точнее 0,4) В (конечно, если нигнит нужной стороной поднести).
Вообще согласен, что идея корявая, просто не было в нигазине ни однополярных, ни цифровых датчиков. Откажусь от неё, пожалуй)
0 / 0 / 0
Регистрация: 18.03.2010
Сообщений: 1,112
27.01.2014, 07:43
Нужно делать проще. Ловить смену фронта в оба направления и просто проверять состояние входа.
0
Kuzmits
27.01.2014, 19:54
Цитата Сообщение от OmykymForti
Нужно делать проще. Ловить смену фронта в оба направления и просто проверять состояние входа.
"Далось мне это прерывание?.." - подумал я в три часа ночи и написал
Code
1
2
3
4
5
6
7
8
9
  while(1) {
sost = PC_IDR_bit.IDR1; //Записываем текущее состояние датчика
//задержка 62,5 мкс для исключения дребезга
for(i=0; i<1000; i++) {
asm("nop");
}
if (PC_IDR_bit.IDR1 != sost) obSec++; //Инкрементируем счетчик, если состояние датчика изменилось
if (obSec==167) obSec=0; //Проверяем - не ушел ли он за предел
};
Затем за остаток ночи оформил курсач, утром продемонстрировал и сдал.
Теперь можно спокойно и вдумчиво продолжать изучение микроконтроллеров :)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
27.01.2014, 19:54
Помогаю со студенческими работами здесь

hd44780, stm8l discovery
Пытаюсь сделать подобие меню на 44780 (WH1604A), столкнулся с проблемой - при отладке через IAR с использованием stm8l discovery (т.е....

STM8L Discovery + COM Port
Есть Дисковери, есть программатор с выведенными Rx и Tx от FT232RL (программатор такой http://iosyitistromyss.ru/skorostnoj-av ......

ds18b20 и STM8L – Discovery.
Задумал я подключить датчик ds18b20 STM8L – Dyscovery. Код думаю писать в ИАРе. Погуглил на этот счет. Готового решения не нашел.Вот...

STM8L-discovery + HCSR04
Нужна помощь в написании программы для платы STM8L-discovery (stm8l152c6) и HCSR04. Среда разработки IAR или STVD не важна. Вывод...

10-канальный диммер на STM8L-DISCOVERY
Для школы, где учится мой младший, сделал 10-канальный диммер плавного управления яркостью прожекторов, используя платку STM8L-DISCOVERY....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru