 |
 |
| View previous topic :: View next topic |
| Author |
Message |
JAM2014
Joined: 24 Apr 2014 Posts: 143
|
| Example: EX_EXPIO.c |
Posted: Thu Nov 06, 2025 2:50 pm |
|
|
Hi All,
I’m looking at example program ‘EX_EXPIO.c’ as the basis for a project. I need to read the data from up to 48 serially connected 74LS165 devices. The example program is clear to me for reading only one ‘165, but for multiple devices, it’s not so clear. Is the best way to change ‘NUMBER_OF_74165’ in 74165.c to 48? If so, in ‘EX_EXPIO.c’, how are the individual bytes referenced?
Jack |
|
 |
PrinceNai
Joined: 31 Oct 2016 Posts: 561 Location: Montenegro
|
|
Posted: Fri Nov 07, 2025 1:10 am |
|
|
| For my way of thinking the easiest way would be to declare an 8bit buffer NUMBER_OF_DEVICES big. Each byte of that buffer exactly represents one of the 74165's. Then I'd clock in 8 bits to same variable and move it to the buffer. Increment buffer position. Repeat NUMBER_OF_DEVICES times. That way accessing values later gets simpler. But of course it depends on what you are actually reading. Maybe bit 125 makes more sense to you than Buffer[15] bit 3. |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19982
|
|
Posted: Fri Nov 07, 2025 8:27 am |
|
|
For 48 inputs, you would change the number to 6. Each chip gives 8 pins.
That is why it is set to '1' for the 8 pin example.
The variable ei, passed to the read_expanded_inputs function will have to
become an array of 6 bytes, instead of a single integer. so instead of:
| Code: |
BYTE data;
while (TRUE) {
read_expanded_inputs (&data);
//You will want:
BYTE data[6];
while (TRUE) {
read_expanded_inputs (data); //since the name of an array is it's address
|
The array then contains all 48 bits in the 6 bytes.
For 48 chips the array would have to be 48 bytes.
48 cascaded chips would give 384 inputs, but the scan speed would be
horrendous. Look at doing this some other way. Perhaps 3 or four
separate chains. The practical limit is well below the 'legal' limit. |
|
 |
temtronic
Joined: 01 Jul 2010 Posts: 9594 Location: Greensville,Ontario
|
|
Posted: Sat Nov 08, 2025 6:33 am |
|
|
off the cuff...
Building on the Prince's reply, creating a 'structure' should simplify things ?
48 x 8 is a LOT of bits to keep 'tidy'. If each byte is broken down into 8 bits, they all have unique names, so easy for the program to do stuff.Maybe a 'super structure where all 48 BYTES become one ?
it'd be interesting to see how long it does take to read all 48 '165 devices, though as Mr. T says, breaking it down into smaller 'chains' will help
Now I'm curious as to what the input data is. Might be a better way to read 384 inputs. |
|
 |
PrinceNai
Joined: 31 Oct 2016 Posts: 561 Location: Montenegro
|
|
Posted: Tue Nov 11, 2025 8:07 am |
|
|
Hi,
with this, according to MPLAB SIM, it takes 1,1ms with 64MHz clock to read all 48 chips. That is worst case scenario, where all the inputs are such that the code needs to flip the corresponding bit in the buffer. I do not have those chips, so I can't test if there's a delay or two too many in the code.
| Code: |
//*******************************************************************
// Multiple cascaded 74HC165 chip driver
//
// Pin SH/LD controls what the chip does. When it is low, it samples
// all 8 paralel inputs. CLK has no function in that state.
//
#include <18F46K22.h>
#device ADC=10
#FUSES NOWDT //No Watch Dog Timer
#device ICD=TRUE
#use delay(internal=64000000)
#define SERIAL_DATA PIN_B0
#define CLK PIN_B1
#define SH PIN_B2
#define NUMBER_OF_74165 48
int8 BUFFER_74165 [NUMBER_OF_74165]; //
// global for easier debugging
int8 Bit_Position;
int8 Byte_Position;
int8 Data_Byte = 0b11111111; // this byte is 0 to save some time. Bits only get set as needed, not also cleared
// int8 Data_Byte = 0;
// *********************** FUNCTIONS ********************************
void Read_74165(void){
output_high(SH);
output_high(CLK); // prepare control pin levels
output_low(SH);
delay_cycles(1);
output_high(SH); // latch the state of paralell inputs. Extra delay is added to ensure timing specs are observed at 64MHz and 3,3V
// clock in the data
for(Byte_Position = 0; Byte_Position < NUMBER_OF_74165; Byte_position++){
for(Bit_Position = 0; Bit_Position < 8; Bit_Position++){
// if(input_state(SERIAL_DATA) == 1){
// bit_set(Data_Byte, Bit_Position);
// } // if
// this is worst case scenario for simulator, when every bit gets cleared
if(input_state(SERIAL_DATA) == 0){
bit_clear(Data_Byte, Bit_Position);
} // if
output_low(CLK); // data is shifted out here and present on data pin
delay_cycles(1); // maybe not needed
output_high(CLK);
} // bit loop
BUFFER_74165[Byte_Position] = Data_Byte; // move received byte to buffer
Data_Byte = 0b11111111;
// Data_Byte = 0;
} // byte loop
} // function
// ********************* END OF FUNCTIONS ***************************
// ******************************************************************
void main()
{
output_float(SERIAL_DATA); // make data pin input
while(TRUE)
{
delay_cycles(1);
Read_74165();
delay_cycles(1);
}
}
|
|
|
 |
JAM2014
Joined: 24 Apr 2014 Posts: 143
|
|
Posted: Tue Nov 11, 2025 11:15 am |
|
|
Hi All,
Thanks for the replies!
This is a project to modernize a multi-input datalogger that can have up to 256 inputs. The system currently communicates via RS-232, and I'm tasked with updating the communications interface to USB. In this system, 74LS165 device inputs are wired directly to the datalogger channels, and to hard-wired idle, start and stop bits to form a standard RS232 data transmission. The output of the last 74LS165 is wired to a MAX232, and all the bits are simply shifted out at 9600 baud on command. It's a pretty clever design that's been working well for 30+ years!
I can break up the transmission into a maximum of 12 74LS165's, but it's not clear to me what speed advantage that will bring? All the Load, and Clk signals for all devices are buffered and distributed to all shift registers, but I have the ability to separate these into banks of 12 74LS165's as well! What advantage would I see by breaking the groups of 74LS165's into separate chains? Is is a signal degradation issue?
Jack |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19982
|
|
Posted: Tue Nov 11, 2025 11:34 am |
|
|
OK.
If you are OK to sample and send perhaps only a sample per second,
then what you describe should be OK. Remember you are going to have
to send the serial between taking the readings, and with the amount of
data this will also be slow, You may well find that there are propagation
delays in the real chips, so it may well be slower than your simulation.
On the speed, remember you can output and read say 8bits at a time
by using an 8bit port in parallel to access the chips, so you could read
eight streams at a time in the same time as doing the single bit version.
This would make the time involved 8* faster. Using this approach, you
would get a whole byte for every single transaction. It'd also be even
faster than 8*, since it removes the need for rotation on the bits as they
arrive. |
|
 |
PrinceNai
Joined: 31 Oct 2016 Posts: 561 Location: Montenegro
|
|
Posted: Tue Nov 11, 2025 11:46 am |
|
|
Hi,
the way it is written gets you all the input values in one place. I do not know what advantage breaking into chains would bring, since the vast majority of time gets spent on sampling the serial input anyhow. Maybe if it would be arranged so you read a byte for each clock change, but it might be a nightmare tracking those bits later. Signal degradation should not be an issue, since every 165 is connected only to the next one in chain and output signal is amplified at each stage. I guess it comes down to the speed of sampling you are trying to achieve and what you are doing in parallel with that.
And of course, the receiving end also needs time to do something with the data, before you start the next transmission. |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19982
|
|
Posted: Tue Nov 11, 2025 12:42 pm |
|
|
If you do eight chains, you would get a whole byte comprising all the first
bits from all eight strings in a single read. Much easier, and hugely faster.
No rotations at all involved. Probably about 20* faster possible. |
|
 |
PrinceNai
Joined: 31 Oct 2016 Posts: 561 Location: Montenegro
|
|
Posted: Tue Nov 11, 2025 12:55 pm |
|
|
| I thought about that. Where I'm stuck is how you output that, quickly? Arrange bits as they should be? |
|
 |
PrinceNai
Joined: 31 Oct 2016 Posts: 561 Location: Montenegro
|
|
Posted: Tue Nov 11, 2025 12:59 pm |
|
|
| If it's not a drone or a nuclear reaction, one or two ms to read that much data isn't a lot :-). I guess the actual sending is going to be much slower. But in that case, something else would be used. |
|
 |
temtronic
Joined: 01 Jul 2010 Posts: 9594 Location: Greensville,Ontario
|
|
Posted: Tue Nov 11, 2025 1:48 pm |
|
|
re: I'm tasked with updating the communications interface to USB
OK, the simple 'cheat' , use an RS-232<> USB module ! There ,it's 'updated'.
I know it sounds like you want to totally update the 'device' not just the serial comm portion.
Old skool design.. think 'PC keyboard', aka matrix. 2 ports as rows, 2 ports as columns, so 16x16 matrix. at each point and an optocoupler to get outside signal into the matrix. Old Intel databooks will have the 'details' for 'scan and read'. since everything is bytes it's small and fast.
Only need a PIC with 4 I/O ports. |
|
 |
PrinceNai
Joined: 31 Oct 2016 Posts: 561 Location: Montenegro
|
|
Posted: Wed Nov 12, 2025 4:05 am |
|
|
I did some quick math. The reading of the inputs can be done in 1ms. If you factor in any propagation delays and maybe a 32MHz clock, it could still be achieved in 3ms. The bottle-neck here is getting that data out. At 9600 serial each byte takes over 1ms and you have 260 bytes to transmit. Over a quarter of a second, not even counting reloading and all other delays. Simply pushing this to 115.200 will increase the speed by a factor of 12, meaning you can get the data out in 21ms. I wholeheartedly agree with a serial-usb convertor approach. All the code stays the same. Where does that data go? To a PC? I have good experience with a serial-ethernet convertor, for example USR-TCP232, if you wish to do it over ethernet. Same thing, you work with serial on the PIC side. I did have to buy a program which let me fill that data in an Access database on the other side, though.
Bottom line: it doesn't matter how you read the inputs. Gains in speed will be in transmission. |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19982
|
|
Posted: Wed Nov 12, 2025 6:35 am |
|
|
Er, 256biis, not 256bytes. As he describes it, no extras, just simple data.
My thought was that if you did eight parallel streams, you send the
clocks to all eight streams and read a byte, then load this to the serial
transmit buffer while you clock in the next eight bits,
With eight streams he can do four chips on each stream, so 32 bits on
each, Send one byte, clock the next bit, then send the next byte,
The data clocking is then done while each byte is sending. Total time
just becomes the time to send the bytes. At 115200, the whole read and
transmit could be done in about 3mSec. |
|
 |
PrinceNai
Joined: 31 Oct 2016 Posts: 561 Location: Montenegro
|
|
Posted: Wed Nov 12, 2025 8:13 am |
|
|
| Of course, my bad :-). I still wonder how to combine those bytes you clock in from different streams into original input pattern on the receiving side. But I'm probably too much into arranging everything into bytes. If you know, that the first transfer are inputs 0, 7, 15, .. and the second 1,8,16 and so on it could work equally well and way faster. An info on just how much hurry is the OP to send that out would be welcome. Than the frequency of consecutive transfers. And what is on the receiving end. |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|