Warning pointer targets in passing argument 1 of 'strlen_P' differ in signedness [-Wpointer-sign]
Warning passing argument 6 of 'show_string' from incompatible pointer type [enabled by default]
char может быть знаковым и беззнаковым - смотрите что от вас ожидают, и что вы на самом деле передаёте в strlen. И какой тип char у используемого компилятора задан по умолчанию.baghear писал(а):Warning pointer targets in passing argument 1 of 'strlen_P' differ in signedness [-Wpointer-sign]
Опять-же ожидаемый тип указателя в шестом параметре функции show_string не соответствует тому, что в него передаёте. Код покажете - можно будет сказать точнее.baghear писал(а):Warning passing argument 6 of 'show_string' from incompatible pointer type [enabled by default]
Такой подход с легкой правкой имеет право на жизнь, можно использовать если требуется передавать строке начиная не с первого символа:baghear писал(а):Есть такая функция
void show_string (unsigned char size,unsigned int start_x,unsigned int start_y,unsigned int color,unsigned int phone,const unsigned char *string)
последним параметром надо передать указатель
const unsigned char string_1 [] PROGMEM = "hello";
передаю вот так
show_string(3,4,2,0XAAAA,0XEEEE, &string_1);
Код: Выделить всё
show_string(3,4,2,0XAAAA,0XEEEE, &string_1[3]);Код: Выделить всё
show_string(3,4,2,0XAAAA,0XEEEE, string_1 + 3);да,а прибавление к указателю целого числа N - суть смещение в массиве на N-ое количество элементов.baghear писал(а): а ошибки не выдает когда передаю так
show_string(3,4,2,0XAAAA,0XEEEE, string_1);
Прочитал что при передаче массива по сути передаю указатель на первый элемент.
Код: Выделить всё
show_string(3,4,2,0XAAAA,0XEEEE, "hello");Точно не скажу, но навскидку это настройка компилятора - будет дефолтный char со знаком или без. А вот зачем - этим я как-то не задумывался. Что-то в памяти рядом с триграфами и прочей жуткой легаси болтается - но утверждать не возьмусь.baghear писал(а):Спасибо большое, стало понятнее!!!!
Почему строковый литерал по дефолту signed char?
разве есть смысл учитывать знак при кодировке?
При включении хидеров в сишник - препроцессор формирует один большой файл который и скармливается компилятору. Т.е. выделив массив прямо в хидере - автор выделил его во всех сишниках в которые он будет включен. Компилятор эти массивы так и вставит в результирующие объектные файлы - ведь он работает с одним сишником за проход. После компилятора, как д'Артаньян на белом коне подъезжает линкер и начинает вязать объектники в единое целое. И тут он находит в различных файлах объекты с одинаковыми именами Font8x16 - и резонно начинает нудить про дубликаты символов и отказываться от своей миссии - ему и на самом деле непонятно какие ссылки идут к "тому" экземпляру, а какие к "этому". Но автор, умная голова, объявляет массив в хидере как static и теперь линкер вяжет ссылки из "этого" файла к его собственной копии массива, а из "того" файла - к "той" копии. Вуаля! Автор удовлетворён, счастливы все кроме процессора, ресурсы которого потрачены на несколько копий одних и тех-же данных. Вот где-то так, по моим ощущениям всё и происходило.baghear писал(а):Еще возник вопрос, есть хэдер, который содержит один массив
static unsigned char const Font8x16[95][16] = {.....}
для чего он объявлен как static?
Код: Выделить всё
ISR(INT7_vect){
disable_int7();
PORTB = ~PORTB; // для того что-бы глянуть что прерывание отработало
}
void init_encoders(void){
//disable_int7(); // РУБИМ ПРЕРЫВАНИЕ ПО INT7
cli(); // ВЫРУБАЕМ ПРЕРЫВАНИЯ ГЛОБАЛЬНО
DDRE &= (1<<DDE7);
PORTE &= (1<<PE7);
EICRB |= (1<<ISC71) | (1<<ISC70) | (1<<ISC61) | (1<<ISC60); // INT6 И INT7 СРАБОТАЮТ ПО 2-М ВЫБОРКАМ ВЫСОКОГО УРОВНЯ
sei(); // ГЛОБАЛЬНО РАЗРЕШАЕМ ПРЕРЫВАНИЯ
}
void enable_int7(void){
cli(); // ВЫРУБАЕМ ПРЕРЫВАНИЯ ГЛОБАЛЬНО
EIMSK = (1<<INT7); // РАЗРЕШАЕМ ПРЕРЫВАНИЕ НА INT7
sei(); // ГЛОБАЛЬНО РАЗРЕШАЕМ ПРЕРЫВАНИЯ
}
void disable_int7(void){
cli(); // ВЫРУБАЕМ ПРЕРЫВАНИЯ ГЛОБАЛЬНО
EIMSK &= (1<<INT7); // ЗАПРЕЩАЕМ ПРЕРЫВАНИЕ НА INT7
sei(); // ГЛОБАЛЬНО РАЗРЕШАЕМ ПРЕРЫВАНИЯ
PORTB = 0x00;
}
int main(){
init_encoders(); // НАСТРАИВАЕМ РАБОТУ ЭНКОДЕРОВ
disable_int7();
enable_int7();
while (1)
{
};
return 0;
}
Код: Выделить всё
EIMSK &= ~(1<<INT7);
Код: Выделить всё
enum _flags {
_READ =01, /* файл открыт на чтение */
_WRITE = 02, /* файл открыт на запись */
_UNBUF = 04, /* файл не буферизуется */
_EOF = 010, /* в данном файле встретился EOF */
_ERR = 020 /* в данном файле встретилась ошибка */
};enum _flags это определение типа и если нужно определить функцию принимающую, к примеру, параметр этого типа - вот тут имя и пригодится. Но по характерным признакам данного конкретного случая мы имеем дело с битами в маске - и попытка передать комбинацию битов выдаст предупреждение компиляции. Впрочем использование безымянных перечислений также не возбраняется современными стандартами и было-бы тут уместно.uk8amk писал(а):Какой смысл в названии перечислителя _flags, если оно напрямую не используется?Код: Выделить всё
enum _flags { _READ =01, /* файл открыт на чтение */ [...] };
Обращение в коде происходит к самим константам(_READ,_WRITE и т.д.).
Код: Выделить всё
typedef enum IRQn
{
NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */
MemoryManagement_IRQn = -12, /*!< 4 Cortex-M3 Memory Management Interrupt */
BusFault_IRQn = -11, /*!< 5 Cortex-M3 Bus Fault Interrupt */
бла-бла-бла
} IRQn_Type;Код: Выделить всё
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
{
NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */
}Код: Выделить всё
//*** Пример работы с USART интерфейсом микроконтроллеров AVR ***
#include <avr/io.h>
#include <avr/interrupt.h>
#define BAUDRATE 9600 // Скорость обмена данными
#define F_CPU 8000000UL // Рабочая частота контроллера
unsigned char NUM = 0;
unsigned char count = 0;
unsigned char byte_receive = 0;
unsigned char i = 1;
// Функция задержки в мкс
void _delay_us(unsigned char time_us)
{ register unsigned char i;
for(i = 0; i < time_us; i++)
{
asm volatile(" PUSH R0 ");
asm volatile(" POP R0 ");
}
}
// Функция задержки в мс
void _delay_ms(unsigned int time_ms)
{ register unsigned int i;
for(i = 0; i < time_ms; i++)
{
_delay_us(250);
_delay_us(250);
_delay_us(250);
_delay_us(250);
}
}
#define RS PD2
#define EN PD3
// Функция передачи команды
void lcd_com(unsigned char p)
{
PORTD &= ~(1 << RS); // RS = 0 (запись команд)
PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD)
PORTD &= 0x0F; PORTD |= (p & 0xF0); // старший нибл
_delay_us(100);
PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(100);
PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD)
PORTD &= 0x0F; PORTD |= (p << 4); // младший нибл
_delay_us(100);
PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(100);
}
// Функция передачи данных
void lcd_data(unsigned char p)
{
PORTD |= (1 << RS)|(1 << EN); // RS = 1 (запись данных), EN - 1 (начало записи команды в LCD)
PORTD &= 0x0F; PORTD |= (p & 0xF0); // старший нибл
_delay_us(100);
PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(100);
PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD)
PORTD &= 0x0F; PORTD |= (p << 4); // младший нибл
_delay_us(100);
PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD)
_delay_us(100);
}
// Функция инициализации LCD
void lcd_init(void)
{
_delay_ms(50); // Ожидание готовности ЖК-модуля
// Конфигурирование четырехразрядного режима
PORTD |= (1 << PD5);
PORTD &= ~(1 << PD4);
// Активизация четырехразрядного режима
PORTD |= (1 << EN);
PORTD &= ~(1 << EN);
_delay_ms(5);
lcd_com(0x28); // шина 4 бит, LCD - 2 строки
lcd_com(0x08); // полное выключение дисплея
lcd_com(0x01); // очистка дисплея
_delay_us(100);
lcd_com(0x06); // сдвиг курсора вправо
lcd_com(0x0C); // включение дисплея, курсор не видим
}
// Функция вывода строки на LCD
void lcd_string(unsigned char command, char *string)
{
lcd_com(0x0C);
lcd_com(command);
while(*string != '\0')
{
lcd_data(*string);
string++;
}
}
// Функция передачи данных по USART
void uart_send(char data)
{
while(!( UCSRA & (1 << UDRE))); // Ожидаем когда очистится буфер передачи
UDR = data; // Помещаем данные в буфер, начинаем передачу
}
// Функция передачи строки по USART
void str_uart_send(char *string)
{
while(*string != '\0')
{
uart_send(*string);
string++;
}
}
// Функция приема данных по USART
int uart_receive(void)
{
while(!(UCSRA & (1 << RXC))); // Ожидаем, когда данные будут получены
return UDR; // Читаем данные из буфера и возвращаем их при выходе из подпрограммы
}
// Функция инициализации USART
void uart_init(void)
{
// Параметры соединения: 8 бит данные, 1 стоповый бит, нет контроля четности
// USART Приемник: Включен
// USART Передатчик: Включен
// USART Режим: Асинхронный
// USART Скорость обмена: 9600
UBRRL = (F_CPU/BAUDRATE/16-1); // Вычисляем скорость обмена данными
UBRRH = (F_CPU/BAUDRATE/16-1) >> 8;
UCSRB |= (1 << RXCIE)| // Разрешаем прерывание по завершению приема данных
(1 << RXEN)|(1 << TXEN); // Включаем приемник и передатчик
UCSRC |= (1 << URSEL)| // Для доступа к регистру UCSRC выставляем бит URSEL
(1 << UCSZ1)|(1 << UCSZ0); // Размер посылки в кадре 8 бит
}
// Прерывание по окончанию приема данных по USART
ISR(USART_RXC_vect)
{
NUM = UDR; // Принимаем символ по USART
byte_receive = 1;
uart_send(NUM); // Посылаем символ по USART
if(NUM == 'a') // Если принят символ "a", включаем светодиод
PORTB |= (1 << PB0);
if(NUM == 'b') // Если принят символ "b", выключаем светодиод
PORTB &= ~(1 << PB0);
}
// Главная функция
int main(void)
{
DDRB |= (1 << PB0); // Светодиод
PORTB = 0x00;
DDRC = 0x00;
PORTC = 0xFF;
DDRD = 0b11111110;
PORTD = 0x00;
lcd_init(); // Инициализация LCD
uart_init(); // Инициализация USART
sei(); // Глобально разрешаем прерывания
str_uart_send("Initialization system\r\n"); // Передаем строку по USART
lcd_string(0x80, " AVR USART TEST "); // Выводим строку на LCD
_delay_ms(2500);
lcd_com(0x01); // Очищаем LCD
while(1)
{
if((PINC & (1 << PC0)) == 0) // Если нажата кнопка 1
{
while((PINC & (1 << PC0)) == 0){} // Ждем отпускания кнопки 1
str_uart_send("Button 1 TEST\r\n"); // Передаем строку по USART
lcd_string(0x80, "Button 1 TEST"); // Выводим строку на LCD
_delay_ms(1000);
lcd_com(0x01); // Очищаем LCD
}
if((PINC & (1 << PC1)) == 0) // Если нажата кнопка 2
{
while((PINC & (1 << PC1)) == 0){} // Ждем отпускания кнопки 2
str_uart_send("Button 2 TEST\r\n"); // Передаем строку по USART
lcd_string(0x80, "Button 2 TEST"); // Выводим строку на LCD
_delay_ms(1000);
lcd_com(0x01); // Очищаем LCD
}
if((PINC & (1 << PC2)) == 0) // Если нажата кнопка 3
{
while((PINC & (1 << PC2)) == 0){} // Ждем отпускания кнопки 3
str_uart_send("Button 3 TEST\r\n"); // Передаем строку по USART
lcd_string(0x80, "Button 3 TEST"); // Выводим строку на LCD
_delay_ms(1000);
lcd_com(0x01); // Очищаем LCD
}
if(byte_receive)
{
byte_receive = 0;
count++;
lcd_data(NUM); // Выводим символ на LCD
if(count > 16) // Если строка заполнена
{
count = 0;
lcd_com(0x01); // Очищаем LCD
}
}
}
}Перечисления (enum).uk8amk писал(а): Было бы удобнее собрать эти константные значения в какой-то объект